Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++_Templates_Metaprogramming_Variadic Templates_Template Meta Programming - Fatal编程技术网

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
被推断为literal
43
的类型,即
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...);
    }