vendredi 27 septembre 2019

Substitution failure with `std::function` and previously deduced template parameter - why?

Consider the following code:

template <typename> 
struct S { };

void g(S<int> t);

template <typename T>
void f(T, std::function<void(S<T>)>);

When attempting to invoke

f(0, g);

I get the following error:

error: no matching function for call to 'f'
    f(0, g);
    ^

note: candidate template ignored: could not match 
      'function<void (S<type-parameter-0-0>)>' 
      against 'void (*)(S<int>)'
void f(T, std::function<void(S<T>)>);
     ^

live example on godbolt.org

While I understand that generally the type of the std::function parameter can't be deduced as it is a non-deduced context, in this case T can first be deduced by the passed argument 0.

I would expect that after deducing T=int, the compiler would substitute T everywhere in the signature and then attempt to construct the std::function parameter with the argument g.

Why is that not the case? I presume that the ordering in which substitution/deduction happens has something to do with this, but I'd like to see the relevant Standard wording.

Bonus question: is this something that could potentially be changed in a future Standard while preserving backwards compatibility, or is there a fundamental reason why this kind of substitution doesn't work?

Aucun commentaire:

Enregistrer un commentaire