Pete Kirkham
Pete Kirkham

Reputation: 49331

Overloading operator<< to accept a template function

I'm trying to be able to write an extensible grammar using functions, but can't seem to find the right syntax for accepting a template function. I'm using Visual C++ 2008. It will accept a variable of the same type as the template function, or a similar non-template function, but not the template function itself.

Error 1 error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion) ( line *** )

class Grammar {
    friend Grammar operator << ( const Grammar& lhs, const char* rhs ) {
        return lhs; // append rhs to grammar
    }
    template<typename T>
    friend Grammar operator << ( const Grammar& lhs, T (*rhs) () ) {
        return lhs; // append rhs() to grammar
    }
};

template<typename T>
class ExpressionParticle {
};

template<typename T>
ExpressionParticle<T> Expression () ;

ExpressionParticle<int> ExpressionInt ();

int _tmain ( int argc, _TCHAR *argv[] )
{
    ExpressionParticle<int> (*p)();

    p = Expression<int>;

    Grammar() << "p";
    Grammar() << p;
    Grammar() << ExpressionInt;
    Grammar() << Expression<int>; // ***

What is the type of Expression<int> if it is not the type of p in above? How is its type different to the type of ExpressionInt.

Upvotes: 5

Views: 765

Answers (4)

Carlton
Carlton

Reputation: 4295

MSVC 2013 still contains the same bug, but at least now you can use the newer C++11 alias template syntax if you go with the casting solution:

template <typename T>
using Fptr = ExpressionParticle<T>(*)();

Then do the cast like this:

Grammar() << Fptr<int>(Expression<int>) << endl;

Upvotes: 0

IvanK
IvanK

Reputation: 1

As another work-around, I was able to get it to work on VS2010 by casting. I used the typedef for convenience. VS2008 probably will work the same.

int _tmain ( int argc, _TCHAR *argv[] )
{
   typedef ExpressionParticle< int > (*FCN)();

   ExpressionParticle<int> (*p)() = Expression<int>; 

   Grammar() << "p"; 
   Grammar() << p; 
   Grammar() << ExpressionInt; 
   Grammar() << static_cast< FCN >( Expression<int> );

Upvotes: 0

Nordic Mainframe
Nordic Mainframe

Reputation: 28807

Your code looks OK to me, and g++ is fine with that too. This seems to be weird overload resolution bug in Visual Studio. VS2005 seems to have the same problem. A possible workaround is (tested with VS2005):

template<class T>
T id(T t)  {return t; }
int main ()
{
    ExpressionParticle<int> (*p)();

    p = Expression<int>;

    Grammar() << "p";
    Grammar() << p;
    Grammar() << ExpressionInt;
    Grammar() << id(Expression<int>); // ***
}

Upvotes: 3

Vite Falcon
Vite Falcon

Reputation: 6641

Change this:

class Grammar {
    friend Grammar operator << ( const Grammar& lhs, const char* rhs ) {
        return lhs; // append rhs to grammar
    }
    template<typename T>
    friend Grammar operator << ( const Grammar& lhs, T (*rhs) () ) {
        return lhs; // append rhs() to grammar
    }
};

to this:

class Grammar {
public:
    Grammar& operator << ( const char* rhs ) {
        return *this; // append rhs to grammar
    }
    template<typename T>
    Grammar& operator << ( const T &rhs) {
        return *this; // append rhs() to grammar
    }
};

Upvotes: 0

Related Questions