Does anyone know why the last line in main fails to compile (note it is compilation that fails):
template <typename TT> inline TT getAs();
template <> string getAs() { return "bye"; }
template <> int getAs() { return 123; }
class Foo
{
public:
template <typename TT>
inline operator TT() const { return ::getAs<TT>(); }
template <typename TT>
inline string getAs() const { return ::getAs<TT>(); }
};
Foo tempFoo() { return Foo(); }
int main()
{
Foo foo;
string testStringLocal = foo; // OK
int testIntTemp = tempFoo(); // OK
string testStringTemp = tempFoo().getAs<string>(); // OK
const string& testStringTemp2 = tempFoo(); // OK
string testStringTemp3 = tempFoo(); //.getAs<string>(); // FAIL!
}
As I indicated by the comments for main's lines,
const string& instead of stringTried this on VS2010. Note the above code compiles fine in 2005 but I believe 2010 is right.
Implicit conversion to string via operator works fine if I remove the template definition and specializations and simply define each overload explicitly:
class Foo
{
public:
operator string() const { return ::getAs<string>(); }
operator int() const { return ::getAs<int>(); }
...
};
I'd prefer not to use this workaround as it is less maintainable.
Does anyone know of another way to have the last line of main() succesfully compile? I don't think the accepted answer to Explicit conversion and templated conversion operator applies here, because there are multiple conversions possible (char *, alloc, string) regardless of whether templates are involved, and the fact the object is a temporary seems to matter.
EDIT: Original code in this post showed some in-class template specialization, this was an artefact of creating a standalone piece of code for SO from my original source (I moved some namespace-level specializations into class and VS2010 did not complain). The issue is not specialization. I modified the posted code to be closer to original (as I just did), doesn't use in-class specialization (problem still there of course). Derek's answer indicates it might be specific to VS2010.
Don't know about Visual C++ 2010 (version 9.0 I think), but you can't specialize a templated member function in the class itself. It must done at namespace scope, according to the errors emitted by more modern compilers I gave this code to.
So,
#include <string>
using namespace std;
class Foo
{
public:
template <typename TT> inline operator TT() const;
template <typename TT> inline TT getAs() const;
};
template <> inline Foo::operator string() const { return "hi"; }
template <> inline Foo::operator int() const { return 123; }
template <> inline string Foo::getAs() const { return "bye"; }
Foo tempFoo() { return Foo(); }
int main()
{
Foo foo;
string testStringLocal = foo; // OK
int testIntTemp = tempFoo(); // OK
string testStringTemp = tempFoo().getAs<string>(); // OK
string testStringTemp2 = tempFoo(); // OK!
}
Compiles fine with Visual C++ 12.0 and g++ 4.7.2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With