Reputation: 20997
In the following example, template struct A
has a constructor from a function type T()
, and then objects of A
are constructed: one with explicit type specification A<int> x
and the other with template argument auto-deduction A y
:
template<typename T>
struct A{
A(T f()){ f(); }
};
int foo() { return 1; }
int main() {
[[maybe_unused]] A<int> x = foo; // ok everywhere
[[maybe_unused]] A y = foo; // Clang error
}
This program is accepted as a whole by GCC, however Clang cannot auto-deduce the template argument:
error: no viable constructor or deduction guide for deduction of template arguments of 'A'
note: candidate template ignored: could not match 'A<T>' against 'int (*)()'
note: candidate template ignored: could not match 'T ()' against 'int (*)()'
Demo: https://gcc.godbolt.org/z/e9aGqoT1s
Is the program not well-formed, or Clang misses some feature required for auto-deduction?
Upvotes: 1
Views: 157
Reputation: 922
<functional>
has deduction guides that make your code valid since c++17, this does look like a clang bug (?) but I found no defect for this specifically.
You could however put the whole function type as a template parameter:
template<typename T>
struct A{
A(T f){ f(); }
};
int foo() { return 1; }
int main() {
[[maybe_unused]] A x{ foo };
[[maybe_unused]] A y{ foo };
[[maybe_unused]] A z = [](){ return 1; }; // now also works with lambdas!
}
This compiles with clang, GCC, and MSVC: https://gcc.godbolt.org/z/K1v7a4s7o
As an unnecessary bonus, asserting on std::is_invocable:
template<typename T>
struct A{
static_assert(std::is_invocable_v<T>, "not invocable");
A(T f){ f(); }
};
Upvotes: 1