Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic template code compiles on GCC 4.6 but not on clang or GCC 4.7

I have this code (simplified from a more complex version):

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);
}

If I compile it on GCC 4.6.3 using g++ -std=c++0x filename.cpp it compiles fine however on clang 3.0 using clang++ -std=c++0x filename.cpp it throws the following error:

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.

On GCC 4.7.2 there is also an error:

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'

Now the question is: why is it failing or what am I doing wrong?

like image 849
eyelash Avatar asked Feb 02 '13 17:02

eyelash


1 Answers

As part of resolving http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1399, it was decided that a parameter pack that is non-deducible will not participate in deduction, hence keeping the explicitly specified arguments within the parameter list, but not disturbing the matching of subsequent arguments to subsequent function parameters. However those added rules do not necessarily apply for deduction when comparing types (which is a sub-algorithm of the deduction of the set of parameters against the arguments for a function call).

I would argue that the resolution should apply to your situation aswell and regard it as simply an area where the specification is not entirely clear. You may want to send a bug report to the respective compilers and they may want to send an issue report to WG21 for asking to clarify this (although I am not sure I would go as far as saying that this is a normative spec issue - the Standard says elsewhere that non-deducible contexts do not participate in deductions).

Note as A1 is a parameter of the enclosing class template (and hence become normal parameters when the class is instantiated), you can omit them and keep the same meaning as far as template argment deduction is concerned

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

    }
};

int main () {
    Test test;
    test.print<int> (1, 1.0f, 1.0); // works
}
like image 73
Johannes Schaub - litb Avatar answered Sep 21 '22 03:09

Johannes Schaub - litb