【问题标题】:Can I define a variadic template function on a single type?我可以在单一类型上定义可变参数模板函数吗?
【发布时间】:2013-12-15 05:14:27
【问题描述】:

我可以定义一个可变参数模板函数,而不是改变类型,而只是一个单一的?如果我的目标是定义一个只添加可变参数 int 而不是浮点数或其他任何东西的函数,我可以用 template<int....> 语法以某种方式做到这一点吗?

我可以轻松组合的多类型样本:

int add() { return 0; }

template<typename T, typename... TS>
T add(T n, TS... m)
  { return n+add(m...); }

但是我如何只在其中使用int? 显然不能遵循将&lt;int&gt; 放在模板参数列表中的模式,因为我想要一个在(...) 之间而不是&lt;...&gt; 之间接受参数的函数,如下所示:

template<int n>
int constant() { return n; }

constant<4>();  // using the int-template function

因此,对我来说很明显以下方法不起作用。但作为一个起点......

template<int, int...>
int add(int n, int... m)    // error, of course.
  { return n+add(m...); }

如何为add(1)add(1,2)add(1,2,3) 等定义add,但仅限于int-参数。它不应该为add(1.0) 生成float 函数(可能调用会起作用,但这只是因为1.0 被转换为int)。

注意:我的意思不是仅仅将TTS 类型限制为enable_if 等。我只是认为我在这里错过了这种可变参数模板的语法。

【问题讨论】:

  • 这基本上没有意义,只需使用std::initializer_list
  • @aaronman 哦,伙计!缺少明显的。谢谢你。你为什么不把它作为一个答案。除了,我需要写‘add({1,2,3})’,对吧?

标签: c++ templates c++11 variadic-templates


【解决方案1】:

为此,您实际上应该只使用std::initializer_list,这与仅用于一种类型的可变参数函数非常相似。

int add(std::initializer_list<int> list) {
    int sum = 0;
    for (auto i : list) sum += i;
    return sum;
}  

现在你可以这样称呼它int i = add({1,2,3,4,5,6});

如果你真的想要,你可以轻松地在其中放置一个静态断言,它会为你做这件事。

int add() { return 0; }

template<typename T, typename... TS>
T add(T n, TS... m)
{
   static_assert(std::is_same<T,int>::value,"bad type"); 
   return n+add(m...); 
}  

但是 IMO 这完全违背了可变参数模板的目的,并且会使程序更难读写。

【讨论】:

  • 你当然是对的。我只是想确保我不会错过任何语法糖。
  • return i; 此字符串无法编译。
  • @Constructor 抱歉错字,已修复
  • 在此处使用initializer_list 禁用缩小转换;将is_same 用于static_assert 会禁用所有转换。要允许转换(如果您想这样做),您可以使用is_convertible 和转换return n+add(static_cast&lt;int&gt;(m)...);。也可以进行 SFINAE 检查以减少函数模板的贪婪(例如,如果您有重载)。
  • @DyP 太懒了,无论如何,initlists 方法更好,如果你觉得很强烈,你可以回答或编辑我的
【解决方案2】:
int add() { return 0; }

template<typename... TS>
int add(int n, TS... m)
{
    return n + add(m...); 
}

这样的代码有什么问题?

【讨论】:

  • @aaronman 它仅适用于那些可以隐式转换为 int 的类型以及带有初始化列表的解决方案。
  • 带有初始化列表,它会在传递其他内容时发出警告,而你的则不会
  • 其实,这又是一个我没有想到的解决方案,虽然它有点明显。是的,这是一个可变参数模板,它必须停止在int add() 上递归,因此可以这么说,它依赖于int operator+(int)。因此,最后,取决于operator+(int,...) 的被污染的全局重载将默认仅适用于隐式敞篷车。我想这实际上是我想要的,它只有很小的变化。正如我在我的问题中所说,我会允许隐式转换,但可以想出很好的理由来更好地选择initializer_list&lt;int&gt;
  • 各位,我现在应该接受哪个答案?难的。构造函数,我必须选择 aaronmans 答案,因为它更“回答”(而不是作为问题陈述)。但是你当然会得到 +1。
猜你喜欢
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 2015-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多