C++ 可变模板中常数参数的使用
我对以下可变码有两个问题:C++ 可变模板中常数参数的使用,c++,templates,metaprogramming,variadic-templates,template-meta-programming,C++,Templates,Metaprogramming,Variadic Templates,Template Meta Programming,我对以下可变码有两个问题: #include <iostream> template <typename T> T Add(const T& arg_a) { return arg_a; } template <typename T, typename... Pack> T Add(const T& arg_a, const Pack&... arg_list) { return arg_a + Add(arg_li
#include <iostream>
template <typename T>
T Add(const T& arg_a)
{
return arg_a;
}
template <typename T, typename... Pack>
T Add(const T& arg_a, const Pack&... arg_list)
{
return arg_a + Add(arg_list...);
}
int main(int argc, const char* argv[])
{
auto itLocalSum = Add(1, 2, 3, 4, 5);
std::cout << "Sum of Add: " << itLocalSum << "\n";
return 0;
}
#包括
模板
T添加(常数T和参数a)
{
返回arg_a;
}
模板
添加(常数T和参数a、常数包和…参数列表)
{
返回参数a+Add(参数列表…);
}
int main(int argc,const char*argv[]
{
自动itLocalSum=Add(1,2,3,4,5);
std::cout1)只是接收参数而不进行复制。const
只是将它们设置为“只读”,它们不能更改。此外,当您使用const引用时,您可以将右值参数绑定到左值参数,然后还可以将文本传递给您的函数,例如
2) 只要每对解包的第一个参数是整数,就会有一个到int的隐式转换。如果将43
值更改为43.0
,它就可以工作了。此外,使用C++17,您可以放弃Add
函数并使用一个折叠表达式:return(arg_a+…+arg_list);
可能更好的解决方案:
template <typename... Pack>
auto Add(const Pack&... arg_list) {
return (arg_list + ...);
}
模板
自动添加(常量包和参数列表){
返回(arg_list+…);
}
回答问题1
由于某些类型的复制成本很高,如果您只是简单地进行求和,而不修改底层对象,那么pass by const reference就消除了复制对象的成本
例如,如果通过值传递一个大的向量
,则整个向量
将被复制以调用函数,而传递常量引用的速度要快得多(很可能实现为指针副本)
问题2的答案
您的问题是,当您计算43+32.2
时,返回值为int
,丢弃了小数部分。这是因为在此上下文中T
被推断为literal43
的类型,即int
。解决您问题的两种方法:
< L>使用<代码> AutoUs/Cuff>返回值(如果你在C++ 14)
模板
T添加(常数T和参数a)
{
返回arg_a;
}
模板
自动添加(常量T和参数a、常量包和…参数列表)
{
返回参数a+Add(参数列表…);
}
或如果你有C++ 17,只需使用
模板
自动添加(常量包和参数列表)
{
返回(…+参数列表);
}
如果你在C++ 11,使用< /LI>
模板
T添加(常数T和参数a)
{
返回arg_a;
}
模板
typename std::common_type::type Add(常数T和参数a、常数包和参数列表)
{
返回参数a+Add(参数列表…);
}
<> > <代码> STD::普通类型< /COD>不起作用(例如,<代码>添加(a)、'b’、'c'、'd')/c> >,您仍然可以在C++ 11中编写自己的和式推断器:
模板
结构求和;
模板
结构和执行{
使用类型=SUMLETFT;
};
模板
结构和执行{
使用type=typename sum\u t\u impl::type;
};
模板
使用sum\u t=typename sum\u t\u impl::type;
并将返回值类型typename std::common\u type
替换为sum\u t
例如,这适用于带有char
s的包,其中char+char->int
intmain()
{
auto itLocalSum=添加('a','b','c','d');
标准::cout
为什么不通过引用传递参数呢?对于整数,这并不重要,但我可以添加(std::string{“QWER”},std::string{“ASDF”},std::string{“ZXCV”})
,并且复制这些参数会花费相当大的成本
不管怎样,您总是返回左侧类型。这意味着如果您有Add(2,3.5)
,则结果必须是int
,并将其强制转换为该类型
为了避免这种情况,您可以推断返回的类型:
template <typename T, typename... Pack>
auto Add(const T& arg_a, const Pack&... arg_list)
{
return arg_a + Add(arg_list...);
}
模板
自动添加(常量T和参数a、常量包和…参数列表)
{
返回参数a+Add(参数列表…);
}
关于错误的总和…问题是
template <typename T, typename... Pack>
T Add(const T& arg_a, const Pack&... arg_list)
{
return arg_a + Add(arg_list...);
}
在43
之后,32.2
变成32
为了解决这个问题…如果你能使用C++17,你可以使用模板折叠和简单的编写
template <typename ... Ts>
auto Add (Ts const & ... as)
{ return (as + ...); }
为什么参数使用常量引用
当您打算以以下方式调用它时:
auto itLocalSum = Add(1, 2, 3, 4, 5);
参数必须是常量&
或仅仅是值
template <typename T>
T Add(const T& arg_a)
{
return arg_a;
}
template <typename T, typename... Pack>
T Add(const T& arg_a, const Pack&... arg_list)
{
return arg_a + Add(arg_list...);
}
模板
T添加(常数T和参数a)
{
返回arg_a;
}
模板
添加(常数T和参数a、常数包和…参数列表)
{
返回参数a+Add(参数列表…);
}
或
模板
T添加(T参数a)
{
返回arg_a;
}
模板
T添加(T参数a、包装…参数列表)
{
返回参数a+Add(参数列表…);
}
对于简单类型,两者都可以。const&
如果T
的复制成本很高,则效率会更高
当我将浮点数与整数组合使用时,比如add(2.3,43,32.2),它不会向我显示正确的值。我如何修复它
您可以使用43.0
而不是43
使用
Add(2.3,43,32.2)
时,递归调用Add(43,32.2)
返回一个int
并将返回值截断为75
您从何处获得此代码?这不是一个很好的通用编程示例。@max66谢谢,添加到答案中。std::common\u type
不是必需的最佳选项,char
+char
->int
,而common\u typee是char
@Jarod42我添加了一个求和类型推断器。为什么当我删除函数签名中的const关键字时,编译器给我一个错误“无法将参数1从'int'转换为'T&'@KaenbyouRin@cayotee不能将左值引用绑定到。
template <typename ... Ts>
typename std::common_type<Ts...>::type Add (Ts const & ... as)
{
// same body as in C++14
}
auto itLocalSum = Add(1, 2, 3, 4, 5);
template <typename T>
T Add(const T& arg_a)
{
return arg_a;
}
template <typename T, typename... Pack>
T Add(const T& arg_a, const Pack&... arg_list)
{
return arg_a + Add(arg_list...);
}
template <typename T>
T Add(T arg_a)
{
return arg_a;
}
template <typename T, typename... Pack>
T Add(T arg_a, Pack... arg_list)
{
return arg_a + Add(arg_list...);
}