为什么这个可变参数模板是错误的?

时间:2017-01-06 14:51:17

标签: c++ variadic-templates

只是想知道为什么这是无效的:

#include <iostream>

template <std::size_t... Is>
void foo(Is&&... args) {
    std::cout << "foo called with " << sizeof...(Is) << "params\n"; 
}

int main() {
    foo(1, 2, 3, 4); 
}

这似乎是一个非常合理的例子,但我可以在任何编译器上fails

如果我将size_t替换为class,则示例按预期工作。我也尝试使用新的auto模板参数,但没有在线编译器接受这个,所以我不知道这是一个无效的用例还是一致性问题。

2 个答案:

答案 0 :(得分:10)

它不是有效的C ++,这就是原因。

如果使用模板参数1, 2, 3, 4实例化该函数模板,则在将参数替换为模板后,您将获得签名:

void foo(1&&, 2&&, 3&&, 4&&);

这显然不是一个有效的功能。

如果你想编写一个接受任意数量参数但只有它们属于正确类型的函数模板,你可以在C ++ 17中这样做:

template<typename T>
  using is_size_t = std::is_same<T, std::size_t>;

template<typename... T>
  std::enable_if_t<std::conjunction<is_size_t<T>...>::value>>
  foo(T&&... args);

或者(也使用C ++ 17):

template<typename... T>
  std::enable_if_t<(std::is_same_v<std::size_t, T> && ...)>
  foo(T&&... args);

对于C ++ 14,您需要自己实施std::conjunction,例如使用p0032r1

中的and_模板

答案 1 :(得分:2)

我最近一直在使用另一种语言,完全把Monika拉到那里。只是为了补充Jonathan的答案,(感谢解释和评论)这是如何确保所有参数都是size_t类型(我实际上要做的)using concepts

template <class... Is>
    requires (std::is_same<Is, int>::value && ...)
void foo(Is&&... args) { /*...*/ }

甚至(ma fav)由定义专用概念

template <class T> concept bool Integer = std::is_same<T, int>::value; 

template <Integer... Is> void foo(Is&&... args) { /*...*/ }
//        ^^^^^^^awesome

Live