Why isn't the template varadic argument deduction performed on this function pointer?

The following minimal example S::foo

works but S::bar

fails.

The only difference is the order of the parameter packages Ts

and Us

.

struct FPtr

and S::lol

is the best workaround I've found, but it's rather awkward to use in practice.

Why bar

does argument deduction for fail (especially since I have specified the types explicitly, so no deduction should occur at all)? Is this a compiler error (occurs with clang++ 3.5

and g++ 4.9

) or is it 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);
}

      

Error message:

$ 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 ...)) {}
             ^

      

Note. I reported this bug to GCC and LLVM bug tracking.

+3


source to share


1 answer


I tested this code with both Clang and GCC and both of them failed to compile the program. I would say this is a bug in both compilers. A function parameter bundle that occurs before the end of the parameter list is an irrelevant context. After substituting the explicitly given template argument (s), it should construct a function

template<>
S<int>::bar(void (*)(float, int));

      

which should match the challenge. Clang and GCC have had problems in areas like this in the past, and their diagnostics have been known to be less useful. Surprisingly, VC ++ compiles the code.



Consider the following which works under both compilers.

template<class... Ts>
struct S {
    template<class... Us>
    void bar(Us..., Ts...);
};

int main() {
    S<int>().bar<int>(1, 2);
}

      

Your program has the same semantics and should be treated the same.

+3


source







All Articles