What is the purpose of very peculiar behaviour of conversion operator template? Consider the following code:
#include <iostream>
#include <utility>
#include <cstdlib>
#define PP { std::cout << __PRETTY_FUNCTION__ << std::endl; }
struct A
{
template< typename T >
operator T () { PP; return {}; }
template< template< typename ... > class C, typename ...types >
operator C< types... > () { PP; return {}; }
template< typename T >
T operator * () { PP; return {}; }
};
static void f(int) PP
template< typename T >
struct S {};
template< typename T = void >
void g(S< T >) PP
int main()
{
struct B {};
// T A::operator B() [T = B]
B{} = A{};
// C<types...> A::operator S() [C = S, types = <void>]
S< void >{} = A{};
// T A::operator int() [T = int]
// void f(int)
f(A{});
// void g(S<T>) [T = void]
g({});
// expected the same output prepended by "T A::operator int() [T = S<void>]"
// but conversion operator does not involved after first step when matching failed
// and default value of template parameter should be chosen to next try
// error: no matching function for call to 'g'
// note: candidate template ignored: could not match 'S<type-parameter-0-0>' against 'A'
//g(A{});
// error: indirection requires pointer operand ('A' invalid)
//B{} = *A{};
// error: no matching member function for call to 'operator*'
// note: candidate template ignored: couldn't infer template argument 'T'
//B{} = A{}.operator * ();
// error: indirection requires pointer operand ('A' invalid)
//(*A{}).~A();
return EXIT_SUCCESS;
}
Its ability to automatically deduce a returning type required by recepient (left hand side of assignment expression or actual function argument type) is unique as far as I can see. I can't reproduce such behaviour for unary operator *, operator ->, operator () and others.
Aucun commentaire:
Enregistrer un commentaire