On 16/11/2017 21:33, Ireneusz Szcześniak wrote:
Thanks for your email. However, I wonder why the other specializations
are used, and not the one for type Label. If your reasoning was
correct, the code for other specializations (for Label1, Label2, Label3)
would fail to compile too.
In your original post, you don't have any specialisations -- just
overloads. They are not the same thing.
My guess is that for some season a compiler does not consider the
specialization of get_cost for type Label, and reverts to the get_cost
declaration, thus complaining that the type for auto cannot be deduced
simply because there is no definition of the function. There might be
some interplay between function overloading and function template
specialization.
That's true; I didn't try linking so didn't notice that it was indeed
still selecting the T overload instead of the Label<Graph> overload.
I think the issue here is that as Label is an alias, the compiler has
trouble deducing things about it:
1. To the compiler, "l" is a variable with type std::tuple<unsigned>.
2. When calling get_cost, it has to choose between several overloads
-- the Label1/2/3 overloads can obviously be excluded, because
std::tuple is not those types. So the choice is between T and
std::tuple.
3. Vertex<Graph> is also an alias, though, so that is actually
std::tupleGraph::vertex_descriptor.
4. When matching std::tuple<unsigned> to
std::tupleGraph::vertex_descriptor, it does not know what type Graph
is and it cannot infer it from the parameter alone, so cannot resolve
what Graph::vertex_descriptor might be.
5. So it must choose T.
Note that the existence of the T overload doesn't influence this -- if
you comment it out then it will still fail because it still can't deduce
what Graph should be purely from the arguments.
The Label1/2/3 overloads work because the parameter type is actually
Label1<graph> (a real type, not just an alias), and so when matching
const Label1<Graph>& it is able to deduce that Graph=>graph. Once it
knows that then it can find graph::vertex_descriptor.
You can make it work by forgoing the deduction and specifying the Graph
type explicitly:
get_cost<graph>(l);
This forces it to exclude the generic T overload because l isn't a const
graph&, so it will match the const Label<graph>& overload instead.
Another option is to pass a Graph object as an additional parameter
directly; this will allow its type to be deduced and then it will be
able to determine that Graph::vertex_descriptor is an unsigned, and
match the overload.
Still another option is to make Vertex a "real" type; this will make the
parameter std::tuple and again it will be able to match
this by deducing Graph.