Mmmmm
What would be the point of posting all that text here? A link is a
better solution.
Anyway:
<quote>
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());
}
------------------------------------------------------------<end quote>
When I compile that code above I do not get any compile error.
Then, I move the commented out code back in, and compile again.
I obtain:
~/tmp $ gcc cpp1.cpp
cpp1.cpp:11:3: error: no matching function for call to 'f2'
f2(any1()); //compile time error
^~
cpp1.cpp:6:6: note: candidate function not viable: no known conversion
from 'any1' to 'int &' for 1st argument
void f2(int&) { }
^
1 error generated.
~/tmp $
Excellent!
That's exactly what I thought when reading the code above. Where is the
conversion from that structure to an int?
By the way the compiler is:
~/tmp $ gcc -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr
--with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
~/tmp $
OK, I think the example is not quite finished. It should contain a
conversion to int, starting with the given structure. By the way clang
notices that and emits warnings.
But let's assume the conversion is done somewhere and continue with the
actual discussion.
<quote------------------------------------------------------------->
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.
<-------------------------------------------------------------end quote>