Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

templates and casting operators

This code compiles in CodeGear 2009 and Visual Studio 2010 but not gcc. Why?

class Foo
{
public:
    operator int() const;

    template <typename T> T get() const { return this->operator T(); }
};

Foo::operator int() const
{
    return 5;
}

The error message is:

test.cpp: In member function `T Foo::get() const':
test.cpp:6: error: 'const class Foo' has no member named 'operator T'

like image 210
Jonathan Swinney Avatar asked Dec 04 '22 12:12

Jonathan Swinney


2 Answers

It's a bug in G++. operator T is an unqualified dependent name (because it has T in it and lookup will thus be different depending on its type). As such it has to be looked up when instantiating. The Standard rules

Two names are the same if

  • ...
  • they are the names of user-defined conversion functions formed with the same type.

Thus the type name specified after the operator keyword doesn't have to match lexically in any way. You can apply the following work-around to force GCC treating it as a dependent name

template<typename T, typename>
struct identity { typedef T type; };

class Foo
{
public:
    operator int() const;

    template <typename T> T get() const { 
      return this->identity<Foo, T>::type::operator T(); 
    }
};
like image 124
Johannes Schaub - litb Avatar answered Dec 23 '22 13:12

Johannes Schaub - litb


I'm not sure what the exact rules for the names of C++ operators are, but I believe it's trying to call operator T() instead of operator int(). Why not just use a cast:

template <typename T> T get() const { return static_cast<T>(*this); }

I haven't tested this but I believe this will accomplish more or less the same thing. If not, there should be a way to accomplish this without having to call operator T() directly. That's what overloaded operators are for, after all.

like image 21
Chris Lutz Avatar answered Dec 23 '22 12:12

Chris Lutz