I am trying to specify template arguments for a template template conversion operator, but I cannot get the correct syntax.
Same code at http://liveworkspace.org/code/35sqXe$4
When compiling with g ++ 4.7.2
$ g++ -std=c++11 -Wall -W -pedantic "template conversion operator.cpp" Compilation finished with errors: source.cpp: In function 'int main(int, char**)': source.cpp:23:23: error: 'int' is not a template source.cpp:23:30: error: no matching function for call to 'C::operator int()' source.cpp:23:30: note: candidate is: source.cpp:11:24: note: template<int adder> C::operator int() source.cpp:11:24: note: template argument deduction/substitution failed: source.cpp:23:30: note: couldn't deduce template parameter 'adder'
When compiling with g ++ 4.8.0 (20130224)
$ g++ -std=c++11 -Wall -W -pedantic "template conversion operator.cpp" Compilation finished with errors: source.cpp: In function 'int main(int, char**)': source.cpp:23:23: error: 'int' is not a template cout << c.operator int<4>() << endl; ^ source.cpp:23:30: error: no matching function for call to 'C::operator int()' cout << c.operator int<4>() << endl; ^ source.cpp:23:30: note: candidate is: source.cpp:11:24: note: template<int adder> C::operator int() template<int adder> operator int() { return i_ + adder; } ^ source.cpp:11:24: note: template argument deduction/substitution failed: source.cpp:23:30: note: couldn't deduce template parameter 'adder' cout << c.operator int<4>() << endl; ^
When compiling with clang ++ 3.2
$ clang++ -std=c++11 -Wall -W -pedantic "template conversion operator.cpp" Compilation finished with errors: source.cpp:23:12: error: reference to non-static member function must be called cout << c.operator int<4>() << endl; ^~~~~~~~~~~~~~ source.cpp:23:30: error: expected expression cout << c.operator int<4>() << endl; ^ 2 errors generated.
When compiling with icc 13.0.1
$ icc -std=c++11 -Wall -W -pedantic "template conversion operator.cpp" Compilation finished with warnings: source.cpp(11): warning #488: constant "adder" is not used in declaring the parameter types of function template "C::operator int" template<int adder> operator int() { return i_ + adder; } ^
Other then icc warning works fine.
Are these compiler errors? Or is it my syntax that is the problem?
EDIT
Since Jakk asked what is my original / actual problem:
I had a Ptr class (templated by the type that it pointed to), and I wanted to have the conversion in Ptr to const T. (Although I know that it does not matter in this case), I wanted the conversion operator not to be there if T was already a const type. Since you are not specifying the return type or method arguments for the conversion operator, I did enable_if as part of the method template parameters.
As Yakk (and others on other issues) published, a simple template <typename = typename std::enable_if<!std::is_const<T>::value>::type> does not work, because when Ptr is created, T is known by the time the compiler gets to this declaration. Since T is not output, SFINAE is absent. Since we know that !is_const<T>::value is false, there is no "type" element, and the declaration is invalid. The template definition depends on the new type (U) having U, and then checking that U matches T and that T is not a constant, then having an invalid declaration is a valid use of SFINAE and works as expected.
template <typename T> class Ptr { template <typename U, typename = typename std::enable_if<std::is_same<T, U>::value && !std::is_const<U>::value>::type> operator Ptr<const U>() const { return active; } };
But then I said to myself: this is a template member function. These template arguments should not be left by default; they can be specified by anyone who creates this function. For any other function of the xxx operator, the syntax for this is obvious and works (see Operator () above). In this example:
Ptr<const int> ci; ci.operator Ptr<const int><const int, void>();
A void (or any other type there) will indicate the argument of the second transform operator pattern, and the default value containing enable_if will not be considered. This will allow this method to be used when I try to make it non-existent.
But gcc, clang and msvc seem to have problems with this syntax. I assume that since the conversion operator typename is written operator typename , the template arguments confuse the compiler in that they are for the type name and not for the operator.
Itβs true that there are workarounds (just include a conversion operator that has a conversion to const T when T is no longer const), but this is for this particular problem. It may not be possible to specify template arguments for conversion operators, so leave these types for output / default in order. Or maybe there is a syntax for it (icc seems to take it ...), so I open myself up to users who define template arguments and instance creation methods where I don't want them. I already have a solution for my specific problem (use static_assert to check the type in the conversion statement for the time when the type matters), but this question is about the C ++ language and its syntax. The C class on top is the easiest way I could look for this syntax.