Overloading of template function in template class - c++

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.

Related

How does the compiler determine between a function using SFINAE and a standard function if both are viable?

Consider the following code:
#include <iostream>
#include <type_traits>
template <typename T>
class A
{
public:
// Allow func to be called if T is the const version of T2
// e.g., T is 'int const' and T2 is 'int'
template <typename T2,
typename = typename std::enable_if<
std::is_same<T, T2 const>::value>::type>
void func(A<T2> const &)
{
std::cout << "Conversion" << std::endl;
}
// Allow func to be called for same version of T
void func(A const &)
{
std::cout << "No conversion" << std::endl;
}
};
int main()
{
A<int const> a;
a.func(A<int const>{});
return 0;
}
This code, when compiled with GCC-8.3 compiles and produces the output No conversion - it selected the version of func that does not use std::enable_if. However, if I comment out the second version of func, it will still compile and now produce the output Conversion. In other words, both versions of func within A are usable for this method. Given that both overloads are viable, what specific rule is the compiler using to select func(A const &) over the other version (func(A<T2> const &))?
The rule is that if a non function template and a function template specialization have the same signature, then the non function template is chosen over the template specialization. This can be found in [over.match.best]/2
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
[...]
F1 is not a function template specialization and F2 is a function template specialization [...]
You can read about overload resolution here. In particular
If any candidate is a function template, its specializations are generated using template argument deduction, and such specializations are treated just like non-template functions except where specified otherwise in the tie-breaker rules.
And then
Best viable function
For each pair of viable function F1 and F2, the implicit conversion sequences from the i-th argument to i-th parameter are ranked to determine which one is better [...]
F1 is determined to be a better function than F2 if implicit conversions for all arguments of F1 are not worse than the implicit conversions for all arguments of F2, and
[...]
4) [...] F1 is a non-template function while F2 is a template specialization
Basically the same rules apply in this simpler example:
#include<iostream>
template <typename T>
void foo(T i) { std::cout << "template" ; }
void foo(int i) { std::cout << "non template"; }
int main() {
foo(1); // non template
}

overloaded templates resolution

// 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 &) {}

Implications of conversion function template argument deduction in C++

I'm having trouble understanding the implications of the conversion function template argument deduction rules in the C++ standard. The standard states that ([temp.deduct.conv] clause 1, §14.8.2.3.1 in N4594):
Template argument deduction is done by comparing the return type of the conversion function template (call it P) with the type that is required as the result of the conversion (call it A; see 8.5, 13.3.1.5, and 13.3.1.6 for the determination of that type) as described in 14.8.2.5.
where 14.8.2.5 ([temp.deduct.type]) is the section that describes general template argument deduction (though the most common case, function call template argument deduction [temp.deduct.call], no longer seems to point there; did it ever?). The next clause is what confuses me, though (clause 2):
If P is a reference type, the type referred to by P is used in place of P for type deduction and for any further references to or transformations of P in the remainder of this section.
To me, this seems to imply that template <class T> operator T() and template <class T> operator T&() are the same (and specifying both would result in an ambiguity). But that isn't the case in any compiler I've used! For instance:
struct any1 { template <typename T> operator T() { } };
struct any2 { template <typename T> operator T&() { } };
void f1(int) { }
void f2(int&) { }
void f3(int const&) { }
int main() {
f1(any1());
// f2(any1()); compile time error
f3(any1());
f1(any2());
f2(any2());
f3(any2());
}
Live Demo
But if references are ignored, any1 and any2 should have the same behavior, right? Clearly they don't, since f2(any1()) doesn't compile with either gcc or clang, while f2(any2()) compiles fine with both.
The next clause (clause 3, particularly 3.3) confuses things even further:
If A is not a reference type: [...] If P is a cv-qualified type, the top level cv-qualifiers of P’s type are ignored for type deduction.
This, along with clause 2 about the removal of references, would seem to imply that the following code should not compile because of an ambiguity:
struct any3 {
template <typename T> operator T&() { }
template <typename T> operator T const&() { }
};
void f1(int) { }
int main() {
f1(any3());
}
Live Demo
And yet this works fine with both gcc and clang.
What am I missing?
Edit
I should clarify that the way the clang and gcc compilers handle this is exactly what I would expect from a general (relatively advanced) understanding of C++. Some commenters have asked for clarification on what my confusion is (and, implicitly, why I should care). My confusion here is entirely related to trying to understand the implications of the standard. I need a clear understanding of this because I am submitting a paper with code that relies heavily on this working and on my use of it being standards-compliant.
The key point you're missing is that overload resolution still has to happen. Template deduction isn't the end of the story. Addressing both of your examples separately:
To me, this seems to imply that template <class T> operator T() and template <class T> operator T&() are the same (and specifying both would result in an ambiguity). But that isn't the case in any compiler I've used!
The text you cite indicates that deduction of T is the same for both conversion operators, this is true. But the operators themselves are not the same. You have to additionally consider the rules for binding to references, which are enumerated in [dcl.init.ref]. The section is too long to concisely copy, but the reason that this is an error
f2(any1()); // error
is the same reason that f2(1) is an error: you can't bind an lvalue reference to non-const to an rvalue. As a result, even having both operators isn't in of itself ambiguous:
struct X {
template <class T> operator T(); // #1
template <class T> operator T&(); // #2
};
f1(X{}); // error: ambiguous
f2(X{}); // ok! #1 is not viable, calls #2
f3(X{}); // ok! #2 is preferred (per [dcl.init.ref]/5.1.2)
And yet this works fine with both gcc and clang.
struct any3 {
template <typename T> operator T&(); // #3
template <typename T> operator T const&() // #4
};
void f1(int) { }
int main() {
f1(any3());
}
This is an interesting scenario as far as compilers go, because gcc has a bug here. Both candidates should be valid (gcc doesn't consider #4 valid due to 61663). None of the tiebreakers apply on determining best viable candidate, so in this case we have to fall back to [temp.deduct.partial] to determine which candidate is more specializated... which, in this case, is #4.
Template argument deduction for a function template is just one step in the complex process of overload resolution.
§13.3.1 Candidate functions and argument lists
...
7 In each case where a candidate is a function template, candidate function
template specializations are generated using template argument deduction
(14.8.3, 14.8.2).
Template argument deduction is performed for a given function template as if no other function template exists. Reread the section §14.8.2.3 with that in mind, and you will realize that your questions belong to a different part of the standard.
After template argument deduction is performed for all candidate template functions, the best viable function must be selected according to the rules of §13.3.3. If by this time two or more function template specializations are present in the candidate function list, then the best viable function selection process involves partial ordering rules described in §14.5.6.2 (I think it's this section that contains answers to you questions).
Type deduction is a separate step from overload resolution and semantic checking.
struct any1 { template <typename T> operator T() { } };
struct any2 { template <typename T> operator T&() { } };
void f1(int) { }
void f2(int&) { }
void f3(int const&) { }
int main() {
f1(any1());
// f2(any1()); compile time error
f3(any1());
f1(any2());
f2(any2());
f3(any2());
}
Here f2(any1()) and f2(any2()) do behave identically for type deduction. Both deduce T=int. But then that T is substituted into the original declaration to get member specializations any1::operator int() and any2::operator int&(). f2(any1().operator int()) is a semantic error because it attempts to bind a non-const lvalue reference function parameter to an rvalue expression. This makes operator int() a non-viable function; if any1 had other conversion functions, they could be selected by overload resolution.
struct any3 {
template <typename T> operator T&() { }
template <typename T> operator T const&() { }
};
void f1(int) { }
int main() {
f1(any3());
}
Here again, the two template conversion functions do behave identically for type deduction. Both deduce T=int. Then that deduction is substituted into the original declarations to get operator int&() and operator int const&(). Then overload resolution compares those two. By my reading of Clause 13, they are ambiguous, but gcc chooses operator int&() and clang chooses operator int const&()...

When are two function templates considered as partially ordered and when are ambiguous?

I'm completely confused after reading the question How to make these std::function parameters unambiguous?, so far I'd thought I understood what partial ordering of function templates is, but after reading that question I wrote down three examples to check the compiler's behavior, and the results received are hard for me to understand.
Example #1
template <class T>
void foo(T) {}
template <class T>
void foo(T&) {}
int main()
{
int i;
foo<int>(i); // error: call is ambiguous!
}
Question: Both functions are viable, that's obvious, but isn't the one taking T& more specialized than T? Instead, the compiler raises ambiguous call error.
Example #2
#include <iostream>
template <class T>
struct X {};
template <>
struct X<int>
{
X() {}
X(X<int&> const&) {} // X<int> is constructible from X<int&>
// note: this is not a copy constructor!
};
template <>
struct X<int&>
{
X() {}
X(X<int> const&) {} // X<int&> is constructible from X<int>
// note: this is not a copy constructor!
};
template <class T>
void bar(X<T>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
template <class T>
void bar(X<T&>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
int main()
{
bar<int>(X<int>()); // calls void bar(X<T>) [with T = int]
bar<int>(X<int&>()); // calls void bar(X<T&>) [with T = int]
}
Question: If the T& and T are ambiguous in Example #1, then why here none call is ambiguous? X<int> is constructible from X<int&>, as well as X<int&> is constructible from X<int> thanks to provided constructors. Is it because compiler generated X<int>::X(X<int> const&) copy-constructor is a better conversion sequence than X<int>::X(X<int&> const&), (if so, what makes it better, note that arguments are passed by value), and so the ordering of specializations does not matter at all?
Example #3
#include <iostream>
// note: a new type used in constructors!
template <class U>
struct F {};
template <class T>
struct X
{
X() {}
template <class U>
X(F<U> const&) {} // X<T> is constructible from any F<U>
// note: it takes F type, not X!
};
template <class T>
void qux(X<T>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
template <class T>
void qux(X<T&>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
int main()
{
qux<int>(F<int>()); // calls void qux(X<T&>) [with T = int]
qux<int>(F<int&>()); // calls void qux(X<T&>) [with T = int]
}
Question: Now this is similar scenario to "matching lambda [](int){} against std::function<void(int&)> and std::function<void(int)>" from question linked. Why in both calls the more specialized function template is picked? Is it because the conversion sequence is the same, so partial ordering starts to matter?
All tests done on GCC 4.9.0 with -std=c++11 and no extra flags.
Overload resolution tries to find the best function like this:
(1) [over.match.best]/1:
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, — the context is an
initialization by user-defined conversion (see 8.5, 13.3.1.5, and
13.3.1.6) and the standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the entity being
initialized) is a better conversion sequence than the standard
conversion sequence from the return type of F2 to the destination
type. [ Example:
struct A {
A();
operator int();
operator double();
} a;
int i = a; // a.operator int() followed by no conversion is better
// than `a.operator double()`
// followed by a conversion to `int`
float x = a; // ambiguous: both possibilities require conversions,
// and neither is better than the other
— end example ] or, if not that, — F1 is a non-template
function and F2 is a function template specialization, or, if not
that, — 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.
Case 1:
but isn't the one taking T& more specialized than T?
According to overload resolution, no conversion is better (both are identity conversions, which are exact matches), and since no other bullet in (1) applies, partial ordering is done. [temp.deduct.partial]/5 says that references are replaced by the type they refer to for purposes of partial ordering:
Before the partial ordering is done, certain transformations are
performed on the types used for partial ordering: — If P is a
reference type, P is replaced by the type referred to. — If A is a
reference type, A is replaced by the type referred to.
Since the parameters of the parameter templates are completely identical it is not hard to see that the deductions against each other are successful both ways -- so neither template is more specialized than the other.
Case 2:
Partial ordering isn't needed here. The user-defined-conversion from X<int> to X<int&> has a worse rank than converting X<int> to X<int> -- The latter is given Exact Match rank by [over.ics.user]/4:
A conversion of an expression of class type to the same class type is
given Exact Match rank, […]
Thus it's obviously a better conversion than X<int> to X<int&>, which has Conversion rank. Same goes vice versa, for X<int&> to X<int>.
Case 3:
The third case is similar to the first. X<int> and X<int&> both have a constructor template that can take an arbitrary specialization of F. (1) tells us that since none of the conversion sequences is better than the other in any way (in fact, they are completely identical), the more specialized template is chosen.
template <class T> void bar(X<T>); // #1
template <class T> void bar(X<T&>); // #2
// Call:
bar<int>( F<int>() );
Going back to [temp.deduct.partial], type deduction is performed. A unique type, call it Unique, is synthesized for the template parameter of each argument template. The following procedures with corresponding results are carried out - note that the steps are exactly the same when calling with F<int> as with F<int&> (and any other specialization of F):
template #1 as the parameter template and template #2 as the argument template, X<Unique&> is deduced against X<T>, yielding T=Unique&. On the other hand,
template #2 as the parameter template against template #1 as the argument template, X<Unique> is deduced against X<T&>, which results in a deduction failure.
As we can see template #2 is more specialized. When used as an argument template in step 1, deduction succeeded, whereas for template #1 as the argument template in step 2, the deduction failed. Therefore the second, more specialized function templates' specialization is called.
Example 1 :
The compiler cannot know if you want to pass a by reference or by value. If you specialize your template with a T * he will know easily because the function call syntax will be different foo(&a).
Example 2 :
Here you tell the compiler that the second overload of qux takes a X<T &> so he knows that you want to construct this object with an T &. There is no ambiguity. But if you do this :
template <class T>
void qux(X<T>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
template <class T>
void qux(X<T> &) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
You will end up with the same problem
Example 3:
Same problem.
I don't know if it's very clear so if someone could improve my answer, that could be useful to the author

Why does compiler not throw compilation error?

Why does compiler allow this?
#include <iostream>
using namespace std;
template<typename T>
void func(T t)
{
cout<<"The value is :"<<t<<"\n";
}
template<>
void func<int>(int d) //Template Specialization
{
cout<<"Template function\n";
}
void func(int d) //Non-template function with same name & signature
{
cout<<"Non-template function\n";
}
int main()
{
func(4);
func(4.67);
func("TENE");
}
The answer to the question lies in section 13.3.3
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,
— F1 is a non-template function and F2 is a function template specialization, or, if not that,
— 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.5.2, or, if not that, ...
So amongst the three choices (non-templated func, specialization of func<int>, and the generic template func<typename T>, the non-template version of func is the best. Since there is a perfect match here, there is no reason for the compiler to even look to the templated versions of the function.
Because this code is perfectly legal. See this article for resolution rules.