Tutorial :Overloading operator<< to accept a template function



Question:

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.


Solution:1

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>); // ***  }  


Solution:2

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      }  };  


Solution:3

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


Solution:4

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;  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »