Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 确定最便宜参数类型的编译时方法_C++_Stl - Fatal编程技术网

C++ 确定最便宜参数类型的编译时方法

C++ 确定最便宜参数类型的编译时方法,c++,stl,C++,Stl,我有一个像这样的模板 template <typename T> class Foo { public: Foo(const T& t) : _t(t) {} private: const T _t; }; 模板类Foo { 公众: Foo(const T&T):\u T(T){ 私人: 康斯特; }; 在参数类型像bool或char这样微不足道的情况下,是否有一种精明的模板元编程方法来避免使用const引用?比如: Foo(stl::smarter_ar

我有一个像这样的模板

template <typename T> class Foo
{
public:
    Foo(const T& t) : _t(t) {}
private:
    const T _t;
};
模板类Foo
{
公众:
Foo(const T&T):\u T(T){
私人:
康斯特;
};
在参数类型像bool或char这样微不足道的情况下,是否有一种精明的模板元编程方法来避免使用const引用?比如:

Foo(stl::smarter_argument<T>::type t) : _t(t) {}
Foo(stl::smarter_参数::类型t):_t(t){

我认为正确的类型特征是
是标量。这项工作如下:

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;
};
模板
结构智能参数{
使用type=const T&;
};
模板
结构智能参数{
使用类型=T;
};
编辑:

以上内容仍然有点老套,感谢@HolyBlackCat提醒我这个更简洁的版本:

template<class T>
using smarter_argument_t = std::conditional_t<std::is_scalar_v<T>, T, const T&>;
模板
使用更智能的参数\u t=std::conditional\u t;

我会使用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;
}

我建议使用
sizeof(size\u t)
(或
sizeof(ptrdiff\u t)
)返回与您的机器相关的“典型”大小,希望此大小的任何变量都能放入寄存器。在这种情况下,您可以通过值安全地传递它。此外,正如@n314159所建议的那样(参见本文末尾的评论),确保变量也是可复制的非常有用

下面是一个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
}
#包括
#包括
#包括
#包括
模板
结构可能参考
{


使用type=std::conditional_tI不会担心它,如果函数很小,编译器将内联它,引用甚至不存在。如果函数很大,将整数包装到引用中的微小成本将很小。我猜,更担心的是完美转发,而不是避免对小数据类型的引用在大多数情况下,按r值传递引用可以优化为按值传递。需要记住的是,答案中没有指出:您所做的将破坏隐式推导指南。如果您关心为
Foo
@TarekDa工作的类模板参数推导,请记住编写显式推导指南khran scalar包含的指针和枚举不是基本的,应该通过值IMO传递。我不熟悉class=void语法。这是否意味着它可以是任何东西,因为它被忽略了?
=void
意味着它有一个默认类型为void,所以使用
智能参数实际上是
智能参数
。我为这个参数留下了一个名称,因为我们不需要它,因此
class=void
没有名称。重要的是
std::enable_if_t
在启用的情况下也必须是void才能匹配默认类型。可以使用更智能的参数=std::conditional\t;
std::condition将其简化为
模板nal_t
std::enable_if_t
可以通过使用C++20概念来大大简化。请注意,没有“计算机的指针大小”这样的东西:
struct Foo{void bar(){};int i;};std::cout@BlueTune有趣,谢谢您的评论。另请参见您的示例:指针和函数指针可能有不同的大小。即使不同的指针也可能有不同的大小。其目的是获得机器的“典型”大小。我已将不明确的sizeof(void*)替换为sizeof(size\t)@Picaud也许你想使用
你可能还想检查
T
是否可以复制。例如,在我的平台上,一个共享指针的大小只有
size\u T
的两倍,并且它可以用一个指针来实现,使其降到相同的大小。但是你肯定想通过const ref而不是按值。@n314159是的,这将是一个改进。如果在我的答案中包含您的想法,您可以吗?很有趣。使用const auto&作为构造函数参数有好处吗?@cppguiy:我很高兴您问这个问题。如果我将参数“const auto&t”替换为“const t&t”,代码将无法编译。错误如下:“…对'Foo'的模板参数的不明确推断…”。。。"。也许你能找到原因?@cppguy:我们的讨论导致了我提出的一个问题。你可以找到。概念在这里是多余的,而且比替代品更难阅读。@S.S.安妮:使用C++20概念从来都不是多余的。它只是很优雅。我到目前为止看到的替代品更难阅读,因为使用嵌套模板。
#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
}