다음과 같은 템플릿이 있습니다
template <typename T> class Foo
{
public:
Foo(const T& t) : _t(t) {}
private:
const T _t;
};
인수 유형이 부울 또는 문자와 같이 사소한 경우 const 참조를 사용하지 않는 정통한 템플릿 메타 프로그래밍 방법이 있습니까? 처럼:
Foo(stl::smarter_argument<T>::type t) : _t(t) {}
답변
나는 올바른 유형의 특성이 있다고 생각합니다 is_scalar
. 이것은 다음과 같이 작동합니다.
template<class T, class = void>
struct smarter_argument{
using type = const T&;
};
template<class T>
struct smarter_argument<T, std::enable_if_t<std::is_scalar_v<T>>> {
using type = T;
};
편집하다:
위의 내용은 여전히 약간 오래된 학교입니다. @ HolyBlackCat이 더 간결한 버전을 상기시켜 주셔서 감사합니다.
template<class T>
using smarter_argument_t = std::conditional_t<std::is_scalar_v<T>, T, const T&>;
답변
이 크기의 모든 변수가 레지스터에 적합하기를 희망하면서 컴퓨터와 관련된 “일반적인”크기를 반환하는 sizeof(size_t)
(또는 sizeof(ptrdiff_t)
) 를 사용하는 것이 좋습니다 . 이 경우 값으로 안전하게 전달할 수 있습니다. 또한 @ n314159 (이 게시물의 끝 부분에있는 주석 참조)에서 제안한 것처럼 변수도 역시 확인하는 것이 유용합니다 trivialy_copyable
.
다음은 C ++ 17 데모입니다.
#include <array>
#include <ccomplex>
#include <iostream>
#include <type_traits>
template <typename T>
struct maybe_ref
{
using type = std::conditional_t<sizeof(T) <= sizeof(size_t) and
std::is_trivially_copyable_v<T>, T, const T&>;
};
template <typename T>
using maybe_ref_t = typename maybe_ref<T>::type;
template <typename T>
class Foo
{
public:
Foo(maybe_ref_t<T> t) : _t(t)
{
std::cout << "is reference ? " << std::boolalpha
<< std::is_reference_v<decltype(t)> << std::endl;
}
private:
const T _t;
};
int main()
{
// with my machine
Foo<std::array<double, 1>> a{std::array<double, 1>{}}; // <- by value
Foo<std::array<double, 2>> b{std::array<double, 2>{}}; // <- by ref
Foo<double> c{double{}}; // <- by value
Foo<std::complex<double>> d{std::complex<double>{}}; // <- by ref
}
답변
C ++ 20 키워드를 사용 requires
합니다. 그냥 이렇게 :
#include <iostream>
template<typename T>
class Foo
{
public:
Foo(T t) requires std::is_scalar_v<T>: _t{t} { std::cout << "is scalar" <<std::endl; }
Foo(const T& t) requires (not std::is_scalar_v<T>): _t{t} { std::cout << "is not scalar" <<std::endl;}
private:
const T _t;
};
class cls {};
int main()
{
Foo{true};
Foo{'d'};
Foo{3.14159};
cls c;
Foo{c};
return 0;
}
온라인 으로 코드를 실행 하여 다음 출력을 볼 수 있습니다 .
is scalar
is scalar
is scalar
is not scalar