Reputation: 569
Why does overload resolution fail in this case ? I would have expected that foo<int>
could be deduced.
template <typename T> struct Templ { typedef T Type; };
template <typename T> void foo(typename Templ<T>::Type) {}
foo(1); //error can't deduce template argument for T
Upvotes: 0
Views: 67
Reputation: 7508
The rules of C++ say that's not a deduced context. If one thinks about why that might be, there are a few things that comes to mind.
Deduction in this case is asking the compiler to invert a type-level function. That may be ambiguous or impossible. That requires introducing rules around specialization visibility. And such a function may be complex even when the solution is unambiguous:
template <std::uint32_t>
struct foo;
template <>
struct foo<0u> {
using type = std::integral_constant<int, 1>;
};
template <>
struct foo<1u> {
using type = std::integral_constant<int, 2>;
};
template <std::uint32_t N>
struct foo {
using type = std::integral_constant<int,
foo<N-1>::type::value + foo<N-2>::type::value
>;
};
template <std::uint32_t N>
void using_foo(typename foo<N>::type);
// would deduce N=20u
using_foo(std::integral_constant<int, 17711>{});
Additionally, it seems like deduction in such cases would introduce ODR hazards. By calling a function, with some arbitrary parameter, we would be deducing a parameter type through an unrelated type-function, and we require that the relevant specializations of that type-function be visible, which isn't something that's obvious at all at the call site.
Upvotes: 2