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.
Related
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.
Consider (link):
#include <cstdlib>
#include <cassert>
#pragma pack (1)
template <size_t Width>
class Base
{
public:
char mData [Width];
template <typename Field> Field ExtractAs () const
{
return *reinterpret_cast <Field> (mData);
}
};
template <typename FieldVal>
class IntegralField
:
public Base <sizeof (FieldVal)>
{
public:
FieldVal GetVal () const
{
return ExtractAs <FieldVal> ();
}
};
int main()
{
char raw[4] = {0x11, 0x22, 0x33, 0x44};
typedef IntegralField <uint32_t> UInt32Field;
const UInt32Field& field =
*reinterpret_cast <const UInt32Field*> (raw);
const uint32_t extracted = field.GetVal();
assert (extracted == 0x44332211);
}
The call:
return ExtractAs <FieldVal> ();
Fails to compile under g++ 4.7.2 with:
main.cpp: In member function ‘FieldVal IntegralField<FieldVal>::GetVal() const’:
main.cpp:25:16: error: ‘ExtractAs’ was not declared in this scope
main.cpp:25:35: error: expected primary-expression before ‘>’ token
main.cpp:25:38: error: expected primary-expression before ‘)’ token
main.cpp: In function ‘int main()’:
main.cpp:32:28: error: ‘uint32_t’ was not declared in this scope
main.cpp:32:36: error: template argument 1 is invalid
main.cpp:32:49: error: invalid type in declaration before ‘;’ token
main.cpp:35:11: error: ‘uint32_t’ does not name a type
main.cpp:36:5: error: ‘extracted’ was not declared in this scope
ninja: build stopped: subcommand failed.
I have tried a number of tricks including using Base::ExtractAs, typedefs, etc, to no avail.
Is what I'm trying to do possible in C++03? How can I call a function template in a base class template from a derived class template member function? Note that I cannot use C++11.
Edit: When I redefine GetVal to be more explicit about types:
FieldVal GetVal () const
{
static const size_t fieldSize = sizeof (FieldVal);
typedef Base <fieldSize> MyBase;
typedef FieldVal MyField;
return MyBase::ExtractAs <MyField> ();
}
I still get:
error: expected primary-expression before ‘>’ token
On: return MyBase::ExtractAs <MyField> ();
Edit: Here is the final, working code:
#include <cstdlib>
#include <cassert>
#include <stdint.h>
#pragma pack (1)
template <size_t Width>
class Base
{
public:
char mData [Width];
template <typename Field> Field ExtractAs () const
{
return *reinterpret_cast <const Field*> (mData);
}
};
template <typename FieldVal>
class IntegralField
:
public Base <sizeof (FieldVal)>
{
public:
FieldVal GetVal () const
{
return this->template ExtractAs<FieldVal>();
}
};
int main()
{
char raw[4] = {0x11, 0x22, 0x33, 0x44};
typedef IntegralField <uint32_t> UInt32Field;
const UInt32Field& field =
*reinterpret_cast <const UInt32Field*> (raw);
const uint32_t extracted = field.GetVal();
assert (extracted == 0x44332211);
}
You can either say:
return this->template ExtractAs<FieldVal>();
Or
return Base<sizeof(FieldVal)>::template ExtractAs<FieldVal>();
Since you are in a class template and the base is a template specialization, too, the names of base members are not automatically injected into the derived template. (Consider what happens if you specialize Base!)
By qualifying the name or using this->, you make the entire name dependent, and so it doesn't cause in error in the first phase. Also, since the name ExtractAs is dependent (being the nested name of a template), you have to disambiguate it as template.
I don't understand what is wrong with the declaration of the derived file. Please help me find the issue with it.
This is the content of my header file:
/*
* STLSandbox.h
*
* Created on: Aug 4, 2012
* Author: aksinghdce
*/
#ifndef STLSANDBOX_H_
#define STLSANDBOX_H_
namespace amit {
class STLSandbox {
public:
STLSandbox();
virtual ~STLSandbox();
};
template<typename T>
class MyCotainer{
public:
virtual void inserthere(T&) = 0;
virtual void deletehere(T&) = 0;
virtual const void printhere(T&) = 0; //promise not to modify anything
};
template<typename T>
class VectorOf: public MyContainer<T>
{
public:
virtual void inserthere(T&);
virtual void deletehere(T&);
virtual const void printhere(T&);
private:
std::vector<T&> v_data; // vector of references of type T
};
template<typename T>
void VectorOf<T>::inserthere(T& item){
v_data.push_back(item);
}
template<typename T>
void VectorOf<T>::deletehere(T& item){
v_data.pop_back(item);
}
template<typename T>
const void VectorOf<T>::printhere(T& item){
std::vector<T>::iterator i = null;
for(i=v_data.begin();i<v_data.end();i++)
{
std::cout<<*i<<std::endl;
}
}
}
#endif /* STLSANDBOX_H_ */
I am using gcc 4.2.1
The following are the error I am getting:
[...]/STLSandbox.h:26: error: expected template-name before ‘<’ token
[...]/STLSandbox.h:26: error: expected `{' before ‘<’ token
[...]/STLSandbox.h:26: error: expected unqualified-id before ‘<’ token
[...]/STLSandbox.h:37: error: ‘template<class T> class amit::VectorOf’ used without template parameters
[...]/STLSandbox.h: In function ‘void amit::inserthere(T&)’:
[...]/STLSandbox.h:38: error: ‘v_data’ was not declared in this scope
[...]/STLSandbox.h: At global scope:
[...]/STLSandbox.h:42: error: ‘template<class T> class amit::VectorOf’ used without template parameters
Looks like its just a typo. You have defined the class MyCotainer (note the missing n) but are using the correct MyContainer later.
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;
So, I'm trying to dabble with the multi_index_container and am having a rather strange compiler error, first here is the simplest example to demonstrate my problem (I'm probably missing something stupidly simple)...
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/mem_fun.hpp>
namespace multi_index = boost::multi_index;
template <typename _IdType>
class A
{
public:
typedef _IdType IdType;
IdType getId() const { return id; }
private:
IdType id;
};
struct id_index{};
template <typename Traits>
class Container
{
typedef typename Traits::AType AType;
typedef typename AType::IdType IdType;
typedef typename multi_index::multi_index_container<
AType,
multi_index::indexed_by<
// sort by Id
multi_index::ordered_non_unique<multi_index::tag<id_index>, BOOST_MULTI_INDEX_CONST_MEM_FUN(AType, IdType, getId) >
>
> ASet;
typedef typename ASet::template index<id_index>::type::const_iterator a_it;
typedef typename ASet::template index<id_index>::type::reverse_iterator a_rit;
typedef typename ASet::template index<id_index>::type id_index_t;
public:
bool addA(AType const& cA)
{
const id_index_t& os = _cSet.get<id_index>(); // line 1: errors occur here
// .. do stuff
return true;
}
private:
// Instance of the container...
ASet _cSet;
};
struct ATraits
{
typedef A<int> AType;
};
int main(void)
{
Container<ATraits> container;
ATraits::AType a;
container.addA(a);
return 0;
}
The errors reported by g++ (gcc 4.4.4, linux) is:
error: expected primary-expression before ‘>’ token (# line 1)
error: expected primary-expression before ‘)’ token (# line 1)
So this was working fine till I converted the Container to a class template, after this, I get this error, and can't work out why..
Any ideas will be appreciated...
bool addA(AType const& cA)
{
const id_index_t& os = _cSet.template get<id_index>(); // line 1: errors occur here
// .. do stuff
return true;
}