expected ';' after expression - c++

I'm trying to port a project from Windows to Mac. I'm having troubles compiling the class CFactory. I'll try to illustrate the problem.
Here's what I have on my Factory.h
namespace BaseSubsystems
{
template <class T>
class CFactory
{
protected:
typedef T (*FunctionPointer)();
typedef std::pair<std::string,FunctionPointer> TStringFunctionPointerPair;
typedef std::map<std::string,FunctionPointer> TFunctionPointerMap;
TFunctionPointerMap _table;
public:
CFactory () {}
virtual ~CFactory();
}; // class CFactory
template <class T>
inline CFactory<T>::~CFactory()
{
TFunctionPointerMap::const_iterator it = _table.begin();
TFunctionPointerMap::const_iterator it2;
while( it != _table.end() )
{
it2 = it;
it++;
_table.erase(it2);
}
} // ~CFactory
}
When I'm trying to compile, the compiler complains:
Factory.h:95:44: error: expected ';' after expression [1]
TFunctionPointerMap::const_iterator it = _table.begin();
^
;
Why is this happening? That am I missing?
NOTE: This project compiles properly on MSVC.
Thanks.

You are missing the required typename keyword when referring to a dependent type. Microsoft Visual Studio incorrectly accepts your code without the typename (this is a well known mistake in VS that will never be corrected).
typename TFunctionPointerMap::const_iterator it;

Related

Boost statechart - compilation error when using state chart as template parameter

I'm trying to implement a simple state machine using boost statechart.
Since I have several variation of this state machine, I thought it might be a good idea to wrap it in a template and pass the state machine as template parameter.
However, I'm getting compilation errors.
Code:
#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/transition.hpp>
namespace sc = boost::statechart;
class ComponentType
{
};
class FSM {
protected:
struct stInit ;
public:
struct Machine : sc::state_machine< Machine, stInit > {};
protected:
struct stInit : ComponentType, sc::simple_state< stInit, Machine > {};
};
template <class fsm>
void run() {
typename fsm::Machine m_fsm;
const ComponentType &t = m_fsm.state_cast<const ComponentType &>();
(void) t;
}
int main() {
run<FSM>();
}
The compilation errors:
fsmtest.cpp: In function ‘void run()’:
fsmtest.cpp:33:45: error: expected primary-expression before ‘const’
const ComponentType &t = m_fsm.state_cast<const ComponentType &>();
^
fsmtest.cpp:33:45: error: expected ‘,’ or ‘;’ before ‘const’
However, when using typedef instead of template:
typedef FSM fsm;
//template <class fsm>
and
run();
// run<FSM>();
Everything compiles without any errors.
What am I missing?
(compiler: g++ 4.8.4, OS: Ubuntu 14.04, boost: 1.54)
You have to let compiler know that you want to call state_cast template function, so it would parse the line correctly. Change:
const ComponentType &t = m_fsm.state_cast<const ComponentType &>();
to:
const ComponentType &t = m_fsm.template state_cast<const ComponentType &>();
Check Where and why do I have to put the "template" and "typename" keywords? for more info.

LLVM vs MSVC function disambiguation

A library that I'm porting from Visual Studio to Xcode uses a template chain. My chain works correctly in Visual Studio. However, when I compile it in Xcode using Apple LLVM 6.0, I get the error
References to overloaded function could not be resolved; did you mean to call it?
Update
I've created a standalone example that compiles in Visual Studio but fails to compile in Xcode with the same error that I'm seeing in my library.
Note: I can probably fix my library code by other means. However, I'd like to take this opportunity for someone to teach me something new about disambiguation and the differences between the compilers. Is this pattern non-standard? Did it only work in Visual Studio because of a language extension?
class Test1{};
class Test2{};
struct NullType{};
template< class T, int id>
class SpecialHandler
{
public:
enum { ETypeId = id };
void handlerFunc( float, int ){}
};
template<typename TReturn, class TObj, typename TParam1, typename TParam2>
class TestResolveClass
{
public:
template< TReturn (TObj::*Func)(TParam1, TParam2 ) >
inline static void funcThatFailsResolve(TObj* obj)
{
(void)obj;
(void)Func;
}
};
template< class TSpecialHandler, class TParent >
class Chain :
public TParent
{
public:
typedef TParent Parent;
typedef TestResolveClass<void, SpecialHandler<Test1, 1>, float, int> TestResolver1;
typedef TestResolveClass<void, SpecialHandler<Test2, 2>, float, int> TestResolver2;
typedef TestResolveClass< void, TSpecialHandler, float, int > TemplatedTestResolver;
void traverseChain()
{
Parent* parentPtr = static_cast<Parent*>( this );
parentPtr->traverseChain(); // up the chain we go
SpecialHandler<Test1, 1> testaroo;
TestResolver1::funcThatFailsResolve< &SpecialHandler<Test1, 1>::handlerFunc >( &testaroo ); // no error
TemplatedTestResolver::funcThatFailsResolve< //<-- Reference to overloaded function could not be resolved; did you mean to call it?
&TSpecialHandler::handlerFunc
>( &m_handler );
TemplatedTestResolver::funcThatFailsResolve< // <-- Reference to overloaded function could not be resolved; did you mean to call it?
static_cast<void (TSpecialHandler::*)( float, int )>( &TSpecialHandler::handlerFunc )
>( &m_handler );
}
private:
TSpecialHandler m_handler;
};
template<>
class Chain< NullType, NullType >
{
public:
void traverseChain(){}
};
typedef Chain< NullType, NullType > ChainLink0;
typedef Chain< SpecialHandler<Test1, 1>, ChainLink0 > ChainLink1;
typedef Chain< SpecialHandler<Test2, 2>, ChainLink1 > ChainLink2;
typedef ChainLink2 FullChain;
class ChainContainer :
public FullChain
{
public:
ChainContainer()
{
traverseChain();
}
};
int main()
{
ChainContainer test;
(void)test;
}
Thanks for your help.
Update 2: I changed a few of the names to be more useful and restructured the code to be clear where the problem is. I also placed some example code before the error to show a situation in which the error does not appear.

Template template parameter errors in MSVC, but not Clang. Why?

I have written this code to help me sort indices that refer to a collection, according to some predicate:
#include <algorithm>
#include <functional>
#include <vector>
template<template<class> class Pred = std::less>
struct element_is_pred
{
template<class C>
struct type : private Pred<typename C::value_type>
{
typedef Pred<typename C::value_type> Base;
C const *c;
type(C const &c, Base const &pred = Base())
: Base(pred), c(&c) { }
bool operator()(
typename C::size_type const i,
typename C::size_type const j) const
{ return this->Base::operator()((*c)[i], (*c)[j]); }
};
};
template<template<class> class P, class C>
static element_is_pred<P>::template type<C const> element_is(
C const &c,
P<typename C::value_type> const &pred = P<typename C::value_type>())
{
return typename element_is_pred<P>::template type<C const>(c, pred);
}
and I'm using it like this:
int main()
{
std::vector<size_t> temp;
std::vector<size_t> indices;
indices.push_back(0);
std::stable_sort(
indices.begin(),
indices.end(),
element_is<std::less>(temp));
}
and when I compile it with Clang 3.2:
clang++ -fsyntax-only Test.cpp
it compiles fine.
But when I try to compile it with Visual C++ 2013, I get tons of errors, like:
test.cpp(23) : warning C4346: 'element_is_pred<Pred>::type<const C>' : dependent name is not a type
prefix with 'typename' to indicate a type
test.cpp(23) : error C2146: syntax error : missing ';' before identifier 'element_is'
test.cpp(23) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Which compiler is correct?
What is the correct way to write the code to do this?
GCC gives the following error:
error: need 'typename' before 'element_is_pred<Pred>::type<const C>' because 'element_is_pred<Pred>' is a dependent scope
Following that advice, I can get the program to build on GCC by prepending typename:
static typename element_is_pred<P>::template type<C const> element_is(
^^^^^^^^
Clang allows the modified version as well.

c++ template syntax error

My C++ is a little rusty having worked in Java and C# for the last half dozen years. I've got a stupid little error that I just cannot figure out.
I've pared the code down as much as possible.
#include <list>
template<class T> class Subscriber
{
virtual void published( T t ) = 0;
};
template <class T> class PubSub
{
private:
std::list< Subscriber<T>* > subscribers;
public:
void publish( T t );
};
template<class T> void PubSub<T>::publish( T t )
{
for( std::list< Subscriber<T>* >::iterator i = subscribers.begin(); i != subscribers.end(); ++i )
i->published( t );
}
When I try and compile this (by including this header file in a code file), I get the following error:
../util/pubsub.h: In member function ‘void PubSub<T>::publish(T)’:
../util/pubsub.h:18: error: expected `;' before ‘i’
../util/pubsub.h:18: error: ‘i’ was not declared in this scope
What am I missing here?
for( typename std::list< Subscriber<T>* >::iterator i = ...
^^^^^^^^
for( typename std::list< Subscriber<T>* >::iterator i = subscribers.begin(); i != subscribers.end(); ++i )
You need the typename because iterator is a dependent name. The compiler has to check the template type T before it knows whether iterator is a type or a value. In those cases, it assumes it to be a value, unless you add typename.
This
std::list< Subscriber<T>* >::iterator
needs to be this
typename std::list< Subscriber<T>* >::iterator
The compiler assumes nested names in templates are static variables (not types) until told otherwise.

How to fix 'expected primary-expression before' error in C++ template code?

Here's yet another VC9 vs. GCC 4.2 compile error problem. The following code compiles fine with VC9 (Microsoft Visual C++ 2008 SP1) but not with GCC 4.2 on Mac:
struct C
{
template< typename T >
static bool big() { return sizeof( T ) > 8; }
};
template< typename X >
struct UseBig
{
static bool test()
{
return X::big< char >(); // ERROR: expected primary-expression
} // before 'char'
};
int main()
{
C::big< char >();
UseBig< C >::test();
return 0;
}
Any ideas how I can fix this?
That should be
return X::template big< char >();
Dependent names from templates are taken to not be types unless you specify that they are via typename and assumed to not be templates unless specified via template.