가장 저렴한 인수 유형을 결정하는 컴파일 시간 방법 : _t(t) {} private:

다음과 같은 템플릿이 있습니다

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


답변