mercredi 24 juin 2015

Why does the variadic template argument deduction fail for this function pointer?

In the following minimal example, S::foo works, but S::bar fails.

The only difference is the order of the parameter packs Ts and Us.

struct FPtr and S::lol are the best workaround I've found, but it's rather uncomfortable to use in practice.

Why does the argument deduction for bar fail (especially since I've explicitly specified the types, so no deduction should happen at all)? Is this a compiler bug (occurs with clang++ 3.5 and g++ 4.9), or is this in the standard, for some reason?

template<typename ... Ts>
struct FPtr {
    FPtr(void (*val)(Ts ...)) : val{val} {}

    void (*val)(Ts ...);
};


template<typename ... Ts>
struct S {
    template<typename ... Us>
    void lol(FPtr<Us ..., Ts ...>) {}

    template<typename ... Us>
    void foo(void (*)(Ts ..., Us ...)) {}

    template<typename ... Us>
    void bar(void (*)(Us ..., Ts ...)) {}
};


void f(int, float) {}
void g(float, int) {}


int main() {
    S<int> s;

    s.lol<float>(FPtr<float, int>(g));
    s.foo<float>(f);
    s.bar<float>(g);
}

The error message is:

$ clang++ -std=c++14 t27.cpp -Wall -Wextra -pedantic
t27.cpp:31:4: error: no matching member function for call to 'bar'
        s.bar<float>(g);
        ~~^~~~~~~~~~
t27.cpp:18:7: note: candidate template ignored: failed template argument deduction
        void bar(void (*)(Us ..., Ts ...)) {}
             ^

Aucun commentaire:

Enregistrer un commentaire