【问题标题】:Variadic template code compiles on GCC 4.6 but not on clang or GCC 4.7可变参数模板代码在 GCC 4.6 上编译,但在 clang 或 GCC 4.7 上不编译
【发布时间】:2013-02-03 21:35:22
【问题描述】:

我有这段代码(从更复杂的版本简化而来):

template <class... A1> class Test {
    public:
    template <class... A2> void print (void(*function)(A2...,A1...)) {

    }
};

void test_print (int a, float b, double c) {

}

int main () {
    Test<float,double> test;
    test.print<int> (&test_print);
}

如果我在 GCC 4.6.3 上使用 g++ -std=c++0x filename.cpp 编译它可以正常编译,但是在 clang 3.0 上使用 clang++ -std=c++0x filename.cpp 它会引发以下错误:

filename.cpp:14:10: error: no matching member function for call to 'print'
    test.print<int> (&test_print);
    ~~~~~^~~~~~~~~~
filename.cpp:3:33: note: candidate template ignored: failed template argument deduction
    template <class... A2> void print (void(*function)(A2...,A1...)) {
                                ^
1 error generated.

在 GCC 4.7.2 上也有错误:

filename.cpp: In function 'int main()':
filename.cpp:14:33: error: no matching function for call to 'Test<float, double>::print(void (*)(int, float, double))'
filename.cpp:14:33: note: candidate is:
filename.cpp:3:33: note: template<class ... A2> void Test::print(void (*)(A2 ..., A1 ...)) [with A2 = {A2 ...}; A1 = {float, double}]
filename.cpp:3:33: note:   template argument deduction/substitution failed:
filename.cpp:14:33: note:   mismatched types 'float' and 'int'

现在的问题是:为什么会失败或者我做错了什么?

【问题讨论】:

  • 您是否尝试删除&lt;int&gt;? C++ 尽可能使用模板类型推导。
  • g++ 4.7 错误信息:ideone.com/qwSKJl 参数排序似乎有问题。
  • @leemes:我试过了,没用
  • 有趣的是,这有效:ideone.com/iVVRKK。闻起来像虫子。
  • 我也认为这是 g++ 中的一个错误。 @eyelash 我感谢你提供了一个最小的例子(这在堆栈溢出时非常罕见);)

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


【解决方案1】:

作为解决http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1399 的一部分,决定不可演绎的参数包将不参与演绎,因此将显式指定的参数保留在参数列表中,但不会干扰后续参数与后续参数的匹配函数参数。但是,在比较类型时,这些添加的规则不一定适用于推导(这是对函数调用的参数进行参数集推导的子算法)。

我认为该解决方案也应适用于您的情况,并将其视为规范不完全清楚的一个领域。您可能希望向各自的编译器发送错误报告,他们可能希望向 WG21 发送问题报告以要求澄清这一点(尽管我不确定我是否会说这是一个规范性规范问题 -标准在其他地方说不可演绎的上下文不参与演绎)。

注意A1是封闭类模板的参数(因此在类实例化时成为普通参数),您可以省略它们,就模板参数推导而言保持相同的含义

class Test {
    public:
    template <class... A2> void print (A2..., float, double) {

    }
};

int main () {
    Test test;
    test.print<int> (1, 1.0f, 1.0); // works
}

【讨论】:

  • 您在示例中删除了函数指针。如果我不删除它仍然会失败:ideone.com/I3KY8d
  • @eyelash 这就是我在回答中所说的。
  • @JohannesSchaub-litb “不可演绎性”是否源于这样一个事实,即有两个参数包(pp)彼此靠近,一个 pp 不是函数的最后一个参数,或者任何其他参数一般规则集?
  • @red 是的,这不是最后一个。
猜你喜欢
  • 1970-01-01
  • 2014-12-04
  • 1970-01-01
  • 2020-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-24
相关资源
最近更新 更多