【问题标题】:incorrect deduction of template parameter pack模板参数包扣错
【发布时间】:2020-04-20 15:52:20
【问题描述】:

以下程序无法编译:

template <unsigned int dim, unsigned int N, bool P, bool C, class... ParametersType>
void test(ParametersType&&... par)
{
}

int main()
{
    test<2, 3, true, false>(2, 1, {8, 8});
}

live on Coliru

错误信息

g++ -std=c++17 -O1 -Wall -pedantic -pthread main.cpp && ./a.out

main.cpp: In function 'int main()':

main.cpp:8:41: error: too many arguments to function 'void test(ParametersType&& ...)
 [with unsigned int dim = 2; unsigned int N = 3; bool P = true; bool C = false; ParametersType = {}]'

    8 |     test<2, 3, true, false>(2, 1, {8, 8});

      |                                         ^

main.cpp:2:6: note: declared here

    2 | void test(ParametersType&&... par)

      |      ^~~~

表示参数包ParametersType...推导为空,而我希望根据传递给test的参数类型推导它。

问题在于传递给test{8, 8} 参数。 将std::array 显式传递给函数可以解决问题:

#include <array>

template <unsigned int dim, unsigned int N, bool P, bool C, class... ParametersType>
void test(ParametersType&&... par)
{
}

int main()
{
    test<2, 3, true, false>(2, 1, std::array<int, 2>{8, 8});
}

live on Coliru

为什么编译器在第一个示例中显然错误地推导出包?

如果编译器无法将{8, 8} 推断为std::array,我预计会出现“无法推断”错误。为什么编译器将包推导出为空包?

【问题讨论】:

    标签: c++ variadic-templates template-argument-deduction


    【解决方案1】:

    模板错误很难纠正。这只是实施的质量。实例的 Clang 给出了

    main.cpp:2:6: note: candidate template ignored: substitution failure 
    [with dim = 2, N = 3, P = true, C = false]: deduced incomplete pack <int, int, (no value)>
    for template parameter 'ParametersType'
    

    这更容易理解。是的,除非使用auto{stuff} has no type

    【讨论】:

      【解决方案2】:

      来自cppreference

      braced-init-list 不是表达式,因此没有类型, 例如decltype({1,2}) 格式不正确。没有类型意味着 模板类型推导不能推导出匹配的类型 支撑初始化列表,所以给定声明模板 void f(T);表达式 f({1,2,3}) 格式不正确。

      您也可以在这种情况下使用auto 来解决您的问题:

      template <unsigned int dim, unsigned int N, bool P, bool C, class... ParametersType>
      void test(ParametersType&&... par)
      {
      }
      
      int main()
      {
         auto x = { 8, 8 };
         test<2, 3, true, false>(2, 1, x);
      } 
      

      【讨论】:

      • 请注意,这里的xstd::initializer_list&lt;int&gt;,而不是std::array
      • @NathanOliver 没错!
      猜你喜欢
      • 2013-06-20
      • 1970-01-01
      • 1970-01-01
      • 2019-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多