overloaded templates resolution - c++

// g++(5.4)
void func(int * const &) {}
void func(int *) {}
template <typename T> void tfunc(const T &) {}
template <typename T> void tfunc(T *) {}
int main()
{
int a = 0;
func(&a); // ambiguous
tfunc(&a); // unambiguous
return 0;
}
According to my another test, tfunc(&a) instantiates the first template to void tfunc(int * const &) which has the same parameter type as the first nontemplate.
So, why is the first call ambiguous but the second not?

Given two function templates that are otherwise equally as good, overload resolution will select the more specialized function template, using a procedure commonly known as partial ordering. The exact rules are pretty complicated, but essentially it tries to determine if the set of arguments template A can be called with is a (proper) subset of the set of arguments template B can be called with. If so, then A is more specialized than B, and overload resolution will prefer A.
Thus, in your case, tfunc(const T&) can be called with ~everything; tfunc(T*) can only be called with pointers. The latter is more specialized, and is therefore selected.
If you are interested in the standardese and detailed rules, see [temp.func.order] and [temp.deduct.partial].

There are some special rules in overload resolution for template functions, one of them is :
F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.
See this question about how to determine which function template is more specialized.
Here, as the second template function is more specialized, there is no ambiguation.
#include <iostream>
void func(int * const &) {}
void func(int *) {}
template <typename T> void tfunc(const T &) {std::cout << "#1\n";}
template <typename T>void tfunc(T *) {std::cout << "#2\n";}
int main()
{
int a = 0;
//func(&a); // ambiguous
tfunc(&a); // unambiguous
return 0;
}
// output: #2
Edit: Though a test in https://ideone.com/C9rF8b , we can see that the second template is chosen, not the first one as stated in the question.

Because a const pointer and a non-const pointer (i.e. T * const and T *) makes no difference if they appear in a function's parameters, and so does passing by value (by copy) and passing by const reference. That's the reason why f(&a) is ambiguous.
For the second one, since &a is resolved to int *, the second template matches better because it's more specialized (it can't accept non-pointer arguments). The first template is more general so it's not used.
If you change the first template function to this it will also be ambiguous:
template <typename T>
void tfunc(T * const &) {}

Related

When to use function full specialization instead of overloading

This question is more theoretical and the scope is different from :
Template Specialization VS Function Overloading - Explaining that the compiler does overload resolution before it even looks at specializations
Template specialization vs. Function overloading - Describing the difference between the two mechanisms
Let's get into theoretical questions:
template <typename T>
T add(T a, T b)
{
return a + b;
}
template <>
int add<int>(int a, int b)
{
return a + b; //Specialization
}
int add(int a, int b)
{
return a + b; //Overloading
}
add(3,4); // in Main
1. When to use function full specialization and when to use function overloading?
Why to use template specialization since the templates are parsed twice (at template definition and at instantiation)?
On the other hand, in the case of function overloading, the answer seems pretty obvious: use it when you have a specific, particular case that needs a different logic rather than the template generic one.
2. Is the lookup process (for gcc or clang) going to choose every time the overloading candidate instead of the specialization if the form is the same? By form I mean: function name, number of arguments, argument types.
In the case of full function specialization, when the template functions are candidates, the compiler selects the template instances. Some are chosen, based on the accepted conversions (in order: strict exact match, qualification adjustment, inheritance derived to base conversion for virtual).
In the case of function overloading, among the candidate functions, select the viable ones for the call. Among the viable functions, select the best match for the call. Basically, the compiler checks the conversion strength (in order: strict exact match, qualification adjustment, int/float promotions, conversions, user conversions such as cast).
Normally, in case of ambiguity for the best viable between a template (specialization) and a non-template (overloading), the compiler selects the non-template. But why? How does the lookup mechanism work?
One factor might be the fact that the supported conversions are not the same.
Example:
template <typename T>
bool isEqual(const T& a, const T& b); //generic form
template <>
bool isEqual(const string& a, const string& b); //specialization
bool isEqual(const string& a, const string& b); //overloading
bool c = isEqual ("cheers", "noroc"); //in Main, the arguments are const char *
In this case, the specialization does not match since it would require a user-defined conversion const char * -> string which is forbidden in argument deduction context.
On the other hand, the overloading match since the user-defined conversion is valid here.
but what if in Main, we give strings as arguments?
string s1, s2;
bool c = isEqual (s1, s2);
Why does the compiler choose the overloading function in this case?
The most fundamental difference is that overloads are found independently by name lookup, whereas specializations are found through the original template itself. The result is that overloads that appear after the call are found only by ADL:
template<class T> void f(T) {} // #1
template<class T> void g(T t) {f(t);}
void f(int) {} // #2
template<> void f(char) {} // #3
namespace N {
struct A {};
void f(A) {} // #4
}
void h() {
f(1); // calls #2
g(1); // calls #1
g('1'); // calls #3
g(N::A()); // calls #4
}
While overload resolution prefers a function over a function template specialization with the same signature, only an explicit specialization completely prevents implicitly instantiating the primary template (which can be selected otherwise with f<>('a')).
Another important (and the most famous) difference is that overloaded function templates behave very similarly to partial specializations (which are not available for function templates). This extends even to picking the best overload when more than one matches (via partial ordering). Of course, the limitation on name lookup pertains, so this isn’t a good means of expressing customizations that might appear after their usage; the idiomatic way to combine these features (and enable template argument deduction) is to have a “front man” function template that forwards calls to the appropriate specialization of a class template (which might be generated from a partial specialization).

Rule for which function overload to specialize

Consider the code:
#include <iostream>
template <typename T>
void f(T)
{
std::cout << "Version 1" << std::endl;
}
template <typename T>
void f(T *)
{
std::cout << "Version 2" << std::endl;
}
template <>
void f<>(int *)
{
std::cout << "Version 3" << std::endl;
}
int main()
{
int *p = nullptr;
f(p);
return 0;
}
This code will output Version 3. What is happening is that function overloading rules look at the first two versions of void f (the third version is a specialization and does not participate in the overload), and decides that the second version is the better version. Once that decision is made, we then see if any specializations exist for the second version. There is, and we use it.
My question, then, is: How did the compiler know that my explicit specialization was a specialization of the second overload and not the first one? I have not provided it with a template parameter for it to make that choice. Is it simply the case that deciding which function to specialize follows a similar/the same rule as deciding which overload to call (if it were calling the function)? That would make some sense...
There is that example in template_argument_deduction#Explicit_instantiation
Template argument deduction is used in explicit instantiations, explicit specializations, and those friend declarations where the declarator-id happens to refer to a specialization of a function template (for example, friend ostream& operator<< <> (...)), if not all template arguments are explicitly specified or defaulted, template argument deduction is used to determine which template's specialization is referred to.
P is the type of the function template that is being considered as a potential match, and A is the function type from the declaration. If there are no matches or more than one match (after partial ordering), the function declaration is ill-formed:
template<class X> void f(X a); // 1st template f
template<class X> void f(X* a); // 2nd template f
template<> void f<>(int* a) { } // explicit specialization of f
// P1 = void(X), A1 = void(int*): deduced X = int*, f<int*>(int*)
// P2 = void(X*), A2 = void(int*): deduced X = int, f<int>(int*)
// f<int*>(int*) and f<int>(int*) are then submitted to partial ordering
// which selects f<int>(int*) as the more specialized template

How does template type deduction work with an overloaded function as the parameter

Look at this (simplified) example:
int foo(int) { return 0;}
double foo(double) { return 0.0; }
template <class T>
enable_if<is_integral<T>::value>
bar(T(*f)(T)) {}
int main()
{
bar(foo);
return 0;
}
My expectation was that the compiler will first try to instantiate the template for each overload, which would fail (SFINAE) for the second overload and therefore there would be only void bar(int(*f)(int) left in the set of candidates, which would resolve using the first overload of foo. That is not what happens. It fails with something like this:
no matching function for call to ‘bar(<unresolved overloaded function type>)’
couldn't deduce template parameter ‘T’
Is there any way to achieve something like this?
C++'s type deduction is very simplistic. The clauses [temp.deduct.call]/6.2 and [over.over]/1 describe ways in which an overloaded name can be used as an argument.
In your example, both the deductions would succeed (to T=int and T=double) and one substitution would fail. But the language requires only one deduction succeed.
You asked how to achieve it. Here are some options:
Do not use an overloaded name, static_cast to the desired function type, or explicitly provide the type of T in the call to bar.
Alter the overloads such that deduction will succeed for only one of the overloads. In other words, exclude overloads by deduction, not by substitution. See below for an example.
Add another parameter which can deduce T.
Pass the buck and avoid deducing T until a later point.
Example for #2:
tempate<class T> struct integral_wrapper { T t; }
integral_wrapper<int> foo(int);
double foo(double);
template<class T>
void bar(integral_wrapper<T> foo(T));
Example for #3:
template<class T>
void bar(T (*f)(T), T);
bar(foo, 0);
Example for #4:
struct foo_t
{
int operator()(int);
double operator()(double);
} foo;
template<class F>
void bar(F);
bar(foo);
Note that a generic lambda can be another approach for #4.
Depending on your usage, some of these may be more attractive than others. Approach #4 is particularly useful when passing arguments to STL algorithms.

Overloading of template function in template class

I have a templated operator in templated class and I want to change its behavior for specific type. My code:
#include <iostream>
template <typename N>
struct A {
int x;
template<typename T>
A& operator<<(const T& t) {
x += static_cast<int>(t);
return *this;
}
};
enum class B {
s,t
};
template <typename N>
A<N>& operator<<(A<N>& a, const B& b) {
a.x -= static_cast<int>(b);
return a;
}
int main() {
A<int> a{3};
std::cout << (a<<1).x << " " << (a << B::s).x;
}
g++-4.9 compiles it fine but clang-3.6 complains that it's ambiguous.
Note, that if class is not templated, than both of compilers compile it fine.
What is correct behavior?
Short summary: I believe this is a gcc bug in the template partial ordering rules, and that clang is correct. I filed bug 66914, although it's probably a duplicate of bug 53499 which I didn't notice until afterwards.
In the call
a << B::s;
We have two viable candidates:
template <typename T> A<int>::operator<<(const T& );
template <typename N> operator<<(A<N>&, const B& );
You can rewrite the member function to take a reference to the instance as the first argument, and write out both as instantiatons. So we have:
template <> operator<<(A<int>&, const B& ); // [T = B]
template <> operator<<(A<int>&, const B& ); // [N = int]
Since both are viable candidates, let's go through the rules in [over.match.best] to determine which one is the best viable candidate:
Given these definitions, a viable function F1 is defined to be a better function than another viable function
F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
— for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,
Nope, both take the exact same arguments, so the conversion sequences are identical.
— the context is an initialization by user-defined conversion [ ... ]
Nope, irrelevant.
— the context is an initialization by conversion function [ ... ]
Nope, irrelevant.
— F1 is not a function template specialization and F2 is a function template specialization, or, if not that,
Nope, both are function template specializations.
— F1 and F2 are function template specializations, and the function template for F1 is more specialized
than the template for F2 according to the partial ordering rules described in 14.5.6.2.
This is the most complicated of the rules. Ultimately, neither is more specialized than the other. Why? The member function is effectively:
template <typename T> A<int>& operator<<(A<int>&, const T& );
If we synthesized a type for T (call it Unique1), deduction would fail against the free function (since Unique1 wouldn't match B). On the other side, if we synthesized a type for N (call it Unique2), deduction would fail against the member function (since Unique2 wouldn't match int).
Since neither function is more specialized than the other, we've run out of bullet points. The function call should be ambiguous, this is a gcc bug.
This:
template <typename N>
A<N>& operator<<(A<N>& a, const B& b) {
a.x -= static_cast<int>(b);
return a;
}
is not an overload of your member operator (I'm sure there is a more correct way to say it from the standardese point of view), and not a specialization, it is a global template operator that participates in overload resolution.
From that point of view both are equally perfect matches so I think clang is correct.

C++ overload function by return type

If I thought I knew anything about C++ then it was that you can't overload functions by return type.
So can anyone explain what is going on here please?
class A { public: typedef int _foo; };
class B {};
template<class T>
typename T::_foo Foo(int)
{
cout << "Foo(int)\n"; return typename T::_foo();
}
template<class T>
typename T Foo(char)
{
cout << "Foo(char)\n"; return typename T();
}
int main()
{
Foo<A>(0); // Writes "Foo(int)", as expected.
Foo<B>(0); // Writes "Foo(char), expected error unable to compile template.
return 0;
}
There are two classes A and B. A defines typedef _foo, B does not. There are two overloads of function template Foo, Foo(int) and Foo(char). Foo(int) returns T::_foo, Foo(char) returns T.
Foo(0) is then called twice. This is an exact match for Foo(int) so I would expect Foo<A>(0) to compile ok, and Foo<B>(0) to fail to compile since B does not define the type _foo used in the template.
What actually happens is that Foo<B>(0) completely ignores Foo(int) and instantiates Foo(char) instead. But by the normal rules of overload resolution Foo(0) is clearly an exact match for Foo(int), and the only thing that makes Foo(char) a more viable match is the return type which should not be considered.
To verify that it is the return value that is affecting the overload resolution just add this:
template<class T>
void Bar(int) { typename T::_foo a; cout << "Bar(int)\n"; }
template<class T>
void Bar(char) { cout << "Bar(char)\n"; }
Bar<A>(0); // Writes "Bar(int), as expected.
//Bar<B>(0); // Error C2039: '_foo' : is not a member of 'B', as expected.
This makes it clear that in the absence of the return value Foo(int) is indeed the correct overload, and that if the template cannot resolve the types used from its template argument that failure to compile is the normal outcome.
You're not overloading on return type, you're specializing a function template and when the Foo<B>(int) specialization forms the invalid type B::_foo that specialization is removed from the overload set by SFINAE, leaving the Foo<B>(char) function as the only viable function.
In more detail, the call to Foo<A>(0) first performs name lookup to find all the Foo names in scope, then instantiates any function templates to find the overload candidates, then overload resolution chooses the best match.
The step of instantiating the function templates produces these two function declarations:
int Foo<A>(int);
A Foo<A>(char);
Overload resolution chooses the first one as the best match.
However when calling Foo<B>(0) the instantiations produce these declarations:
<invalid type> Foo<B>(int);
B Foo<B>(char);
The first declaration is not valid, so there is only one candidate for overload resolution, so that is the one that gets called.
In your Bar example the invalid type that gets formed during instantiation is not in "the immediate context" of the function declaration (it's in the function definition i.e. body) so SFINAE does not apply.
template<class T>
typename T::_foo Foo(int);
template<class T>
typename T Foo(char);
So your code declares this overloaded function. That's nice.
Foo<A>(0);
In this case, the compiler tries to fill out the template for the prototypes declared above, which would be:
int Foo(int);
A foo(char);
And since you're passing an integer as a parameter, the first is a better match, so the compiler uses that one.
Foo<B>(0);
Again the compiler sees this line and tries to fill out the template for the prototypes, but...
WTFDOESNTMAKESENSE?!?!? Foo(int);
A foo(char);
So clearly, the first one doesn't even make sense, so it discards that and uses the second overload. This actually has nothing to do with return types, it has to do with how template prototypes are filled out before it decides which function you mean. Here's your example rearranged to clarify:
template<class T>
int foo(T::_foo) {}
template<class T>
int foo(char) {}
int main() {
foo<A>(0); //uses the first, `int foo(int)` better than `int foo(char)`
foo<B>(0); //uses the second, because the first doesn't work with B.
This is called SFINAE, and note that it only works in very particular circumstances in template parameters, return types, and function parameters, but not the function body itself. This is why your "verification" caused an error, because it can't tell that one of the functions is invalid from the prototype, and the prototype is the only thing considered when it's deciding between overloads.