views:

105

answers:

3

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.

A: 

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
    }
};
Vite Falcon
`Grammar() << Expression<int>();` has a completely different meaning.
Luther Blissett
ah!... my bad.. i didn't notice that part of it. But the way he overloaded the `operator <<` was wrong, IMO. I'll change that now.
Vite Falcon
@Luther I'm sorry.. but wat's the completely different meaning of `Expression<int>();` again? It's a template-function and the function should be called like a function. Isn't it? I worked it out in Visual Studio 2008 and it does compile it!
Vite Falcon
He wants the function pointer Expression<int> not the result from calling Expression<int>. Apparently he wants to call the function later to produce some side effects.
Luther Blissett
+2  A: 

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>); // ***
}
Luther Blissett
A: 

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> );
IvanK