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_C++11_Variadic Templates_Initializer List - Fatal编程技术网

C++ 无法将多个初始值设定项列表传递给变量函数模板

C++ 无法将多个初始值设定项列表传递给变量函数模板,c++,templates,c++11,variadic-templates,initializer-list,C++,Templates,C++11,Variadic Templates,Initializer List,我不理解尝试传递可变数量的初始值设定项列表时出现的错误消息: template<typename... Values> void foo(Values...) { } int main() { foo(1, 2, 3, "hello", 'a'); // OK foo({1}, {2, 3}); // ERROR } 然而,我是否应该不能传递我想要的那么多参数?[]这个问题可能是可推断的{}可以是任何参数的统一初始值设定项 这项工作:

我不理解尝试传递可变数量的初始值设定项列表时出现的错误消息:

template<typename... Values>
void foo(Values...)
{
}

int main()
{
    foo(1, 2, 3, "hello", 'a');   // OK

    foo({1}, {2, 3});             // ERROR
}

然而,我是否应该不能传递我想要的那么多参数?[]

这个问题可能是可推断的
{}
可以是任何参数的统一初始值设定项

这项工作:

#include <initializer_list>

template<typename... Values>
void foo(std::initializer_list<Values>... args)
{
}

template<typename... Values>
void foo(Values&&... args)
{
}

int main()
{    
    foo(1, 2, 3, "hello", 'a');
    foo({1}, {2, 3});
}
#包括
模板
void foo(标准::初始值设定项\u列表…参数)
{
}
模板
void foo(值和参数)
{
}
int main()
{    
foo(1,2,3,“你好”,“a”);
foo({1},{2,3});
}

请参见

问题不在于varadic参数,而是编译器无法推断括号内初始值设定项列表的类型,除非您声明了
std::initializer\u list

§14.8.2.1通过比较每个函数来进行模板参数推导 模板参数类型(称为P)与对应的 调用的参数(称为A),如下所述。如果删除 来自P的引用和cv限定符给出了std::initializer\u列表 对于某些P0,参数是初始值设定项列表(8.5.4),则 对初始值设定项的每个元素执行演绎 列表,以P0为函数模板参数类型和 初始值设定项元素作为其参数否则,为初始值设定项列表 参数导致参数被视为非推断上下文 (14.8.2.5).

下面甚至有一个例子

template<class T> void g(T);
g({1,2,3}); // error: no argument deduced for T
模板无效g(T);
g({1,2,3});//错误:没有为T推导参数

正如其他答案所提到的,问题确实是可推断性。您可以在调用函数时指定foo的参数类型,而不是提供第二个采用初始值设定项\u列表的函数:

#include <initializer_list>

template<typename... Values>
void foo(Values...)
{
}

int main()
{
  foo(1, 2, 3, "hello", 'a');
  foo(std::initializer_list<int>{1}, std::initializer_list<int>{2, 3});
}
#包括
模板
无效foo(值…)
{
}
int main()
{
foo(1,2,3,“你好”,“a”);
foo(std::initializer\u list{1},std::initializer\u list{2,3});
}
然而,决定如何处理每个参数是另一个问题


[编辑]:这个想法来自于

这很糟糕。考虑一个简单的打印()实用程序:

Tuple也可以工作(忽略所需的实现):

但这些都不管用

print({1,2,3}); // spurious error messages
print({1}, {2}, {3}); // also 
print("\nThe tuple: ", {12, 34, 56 } ) ; //also
上述“解决方案”也无济于事:

template<typename ...Args>
inline  void print(const std::initializer_list<Args>&... il_);
这里有什么明显的缺失吗?我想混合调用print()中的任何内容,因为它的声明暗示了这一点

有人吗

[编辑2017-11-08]

有人建议

 print("\nMy list is:\t", std::initializer_list<int>{1,2,3,4}) ;
但遗憾的是,MSVC 14.11.25503(截至本文撰写之时的最新版本)无法编译此文件。错误来自于

    1>c:\program files (x86)\microsoft visual 
    studio\2017\community\vc\tools\msvc\14.11.25503\include\utility(415): 
    error C2027: use of undefined type 'std::tuple_size<_Ty>'
   1>        with
   1>        [
   1>            _Ty=std::initializer_list<int>
   1>        ]
   1>c:\program files (x86)\microsoft visual 
      studio\2017\community\vc\tools\msvc\14.11.25503\include\utility(415): 
      note: see declaration of 'std::tuple_size<_Ty>'
   1>        with
   1>        [
   1>            _Ty=std::initializer_list<int>
   1>        ]
   1>c:\program files (x86)\microsoft visual 
    studio\2017\community\vc\tools\msvc\14.11.25503\include\tuple(1051): 
     note: see reference to variable template 'const ::size_t 
     tuple_size_v<std::initializer_list<int> >' being compiled
我知道C++17初始化列表的类型推导得到了加强和改进,但我看不到有任何东西可以帮助我理解这是可行的吗


最后看来应该是这样。

的确如此<代码>模板无效foo(T)无法从参数
foo({1,2})推断
(参数
T
成为非推断上下文),但有一些特殊规则允许推断
模板void foo(std::initializer\u list)
(和同一个参数)。您能否展开“
{}
可以是任何参数的统一初始值设定项。”部分?我不确定我是否理解你的意思。我的意思是编译器不会“假定”它必须是一个初始值设定项列表(注意,初始值设定项列表中的元素类型不必是同构的)。相反,它可以是任何旧UDT/内置的统一初始化。反之亦然:如果函数重载接受初始值设定项列表,则该重载总是首选接受
{}
样式参数。此参考资料展示了一个非常准确的问题示例@Falmari CPPFREFERENCE以高质量的金块让我惊讶。这不仅仅是一个标准的图书馆参考资料。+1是我的“变通方法”的一个完美的配套引用。确实值得升级为一个答案。谢谢你的钻研
print({1,2,3}); // spurious error messages
print({1}, {2}, {3}); // also 
print("\nThe tuple: ", {12, 34, 56 } ) ; //also
template<typename ...Args>
inline  void print(const std::initializer_list<Args>&... il_);
print("\nMy list is:\t", {1,2,3,4}) ; // error: function print() does not take 2 arguments?
 print("\nMy list is:\t", std::initializer_list<int>{1,2,3,4}) ;
#define DBJ_IL(T,...) (std::initializer_list<T>{__VA_ARGS__})
print("\nMy list is:\t", DBJ_IL(int,1,2,3,4)) ;
    1>c:\program files (x86)\microsoft visual 
    studio\2017\community\vc\tools\msvc\14.11.25503\include\utility(415): 
    error C2027: use of undefined type 'std::tuple_size<_Ty>'
   1>        with
   1>        [
   1>            _Ty=std::initializer_list<int>
   1>        ]
   1>c:\program files (x86)\microsoft visual 
      studio\2017\community\vc\tools\msvc\14.11.25503\include\utility(415): 
      note: see declaration of 'std::tuple_size<_Ty>'
   1>        with
   1>        [
   1>            _Ty=std::initializer_list<int>
   1>        ]
   1>c:\program files (x86)\microsoft visual 
    studio\2017\community\vc\tools\msvc\14.11.25503\include\tuple(1051): 
     note: see reference to variable template 'const ::size_t 
     tuple_size_v<std::initializer_list<int> >' being compiled
/*
forget templates
*/
namespace dbj { namespace {
  auto print = [](auto... param)
  {
   if constexpr (sizeof...(param) > 0) {
    char dummy[sizeof...(param)] = { 
          (( std::cout << param), 0)... 
        };
     }
  };
} }
 dbj::print({1,2,3}) ; // msvc compilation error