Reputation: 2792
Consider the following:
template <typename T> struct template_adapter_t {};
template <int N> struct foo_adapter_t {
template <typename T> static foo_t<T, N> adapt(T const&);
};
template <int N> template_adapter_t< foo_adapter_t<N> > foo();
template <typename Range, typename Adapter>
auto operator|(
Range const& range,
template_adapter_t<Adapter>(*)())
-> decltype(Adapter::adapt(range))
{ return Adapter::adapt(range); }
(So, what is going on here... I have a 'dummy' class, template_adapter_t
, that serves only as a specialization limiter, a concrete helper class foo_adapter_t
, a free function foo
which returns a type of template_adapter_t
, and an overload of operator|
that is supposed to take anything on the LHS, and a pointer to a function that takes no parameters and returns some type of template_adapter_t
on the RHS.)
When I try to use this:
int const values[] = { ... };
values | foo<2>;
...I get an error about invalid operands.
However, this works:
std::vector<int>{} | foo<2>;
This also works:
template <typename Range, int N>
auto operator|(
Range const& range,
foo_adapter_t<N> const& adapter)
-> decltype(adapter.adapt(range))
{ return adapter.adapt(range); }
values | foo_adapter_t<4>{};
...so the problem doesn't seem to be with matching on the LHS. In both cases, the RHS is also templated, but for some reason, the one taking a struct works, but the one taking a function does not.
What am I missing that the alternate invocations work but the first one doesn't? How can I make the first form work?
Upvotes: 2
Views: 118
Reputation: 16404
This is because you can't overload operators for 2 pointers. At least one of the operand should be used-defined class (See here).
In this line:
values | foo<2>;
values
is a pointer to const int
, foo<2>
is a function pointer, thus no overloaded operator will be considered.
Upvotes: 3