C++ expected primary-expression compile error - c++

#include <boost/format.hpp>
#include <boost/scoped_ptr.hpp>
#include <stdexcept>
#include <unordered_map>
#include <functional>
#define DECLARE_OBJECT(classname) namespace {core::declare_object<classname> __declarartion_#classname;}
namespace core {
class dungeon;
class object;
typedef std::function<object* (dungeon *)> object_creator;
namespace library_type {
enum type {
landscape = 0, walker, foe, bonus,object = 42
};
};
struct library_error : public std::logic_error
{
explicit library_error(const std::string &what) : std::logic_error(what) {};
};
template <enum library_type::type type>
class library {
public:
static library<type> *instance() {
if (!m_instance)
m_instance = new library<type>();
return m_instance;
}
template<typename T>
void add_object() {
boost::scoped_ptr<T> obj(T::create(nullptr));
m_library.insert(obj->name(), T::create);
}
const object_creator& get_object(const std::string &key) {
auto lookup_iterator = m_library.find(key);
if (lookup_iterator == m_library.end())
throw library_error(boost::format("Object creator for key `%1%' not found\n") % key);
return *lookup_iterator;
}
private:
library () {};
static library<type> *m_instance;
std::unordered_map<std::string, object_creator> m_library;
};
template <enum library_type::type type>
library<type>* library<type>::m_instance;
template <enum library_type::type type, typename T>
struct declare_object
{
declare_object() {
auto instance = library<type>::instance();
auto method = instance->add_object<T>;
method();
}
};
};
int main()
{
}
Hello. This simple C++0x code gives me error in declare_object constructor
example.cpp: In constructor ‘core::declare_object<type, T>::declare_object()’:
example.cpp:52:43: error: expected primary-expression before ‘>’ token
example.cpp:52:44: error: expected primary-expression before ‘;’ token
I have really no idea where I am wrong. Maybe clear view and suggestions?
Sorry for long listing.
EDIT: Answer was auto method = instance -> template add_object<T>;. Why you deleted your answer?

To get a pointer to member function you need to follow the syntax in the other answer.
Since the member function is furthermore a template, you need to indicate this because it’s a dependent name:
auto method = &library_type<type>::template add_object<T>;
Otherwise C++ will parse the pointy braces in add_object<T> as less-than and greater-than operators.

struct declare_object
{
declare_object() {
auto instance = library<type>::instance();
auto method = &library<type>::template add_object<T>;
(instance->*method)();
}
};

Related

Problem using a self registering factory without passing arguments to base class

I've been trying to implement the Self Registering Factory pattern in my project and, after trying a bunch of ways to do it, I've settled for this solution.
Unfortunately, I've stumbled upon a problem where my code isn't compiling because my base class doesn't have any arguments to pass. There is a comment in the provided link detailing this exact issue but I must say that I don't understand why it doesn't work and how to make it work if possible.
Here is the error I get when compiling:
could not convert ‘std::make_unique(_Args&& ...) [with _Tp = ObjectA; _Args = {}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<ObjectA, std::default_delete<ObjectA> >]()’ from ‘unique_ptr<ObjectA,default_delete<ObjectA>>’ to ‘unique_ptr<BaseClass,default_delete<BaseClass>>’
40 | return std::make_unique<T>(std::forward<Args>(args)...);
| ^
| |
| unique_ptr<ObjectA,default_delete<ObjectA>>
For the sake of clarity, I'll post the code and example of classes I'm trying to implement with it.
selfregisteringfactory.h
#include <memory>
#include <unordered_map>
#include <string>
#include <cstdlib>
#include <cxxabi.h>
std::string demangle(const char *name) {
int status = -4;
std::unique_ptr<char, void (*)(void*)> res{
abi::__cxa_demangle(name, NULL, NULL, &status), free};
return (status == 0) ? res.get() : name;
}
template<class Base, class... Args>
class SelfRegisteringFactory {
public:
template<class ... T>
static std::unique_ptr<Base> make(const std::string &name, T&&... args) {
return data().at(name)(std::forward<T>(args)...);
}
friend Base;
template <class T>
class Registrar : Base {
friend T;
static bool registerT() {
const auto name = demangle(typeid(T).name());
SelfRegisteringFactory::data()[name] = [](Args... args) -> std::unique_ptr<Base> {
return std::make_unique<T>(std::forward<Args>(args)...);
};
return true;
}
static bool registered;
private:
Registrar() : Base(Key{}) { (void)registered;};
};
private:
class Key {
Key(){};
template <class T> friend class Registrar;
};
using FuncType = std::unique_ptr<Base> (*)(Args...);
SelfRegisteringFactory() = default;
static std::unordered_map<std::string, FuncType> &data(){
static std::unordered_map<std::string, FuncType> s;
return s;
}
};
template <class Base, class... Args>
template <class T>
bool SelfRegisteringFactory<Base, Args...>::Registrar<T>::registered =
SelfRegisteringFactory<Base, Args...>::Registrar<T>::registerT();
baseclass.h
#include "selfregisteringfactory.h"
#include <string>
class BaseClass : public SelfRegisteringFactory<BaseClass>{
public:
BaseClass(Key){};
virtual ~BaseClass() = default;
virtual void process() = 0;
virtual std::string getType() = 0;
};
objecta.h
#include "baseclass.h"
class ObjectA: public BaseClass::Registrar<ObjectA>{
public:
ObjectA();
virtual ~ObjectA() = default;
virtual void process();
virtual std::string getType();
};
objecta.cpp
#include "objecta.h"
#include <iostream>
ObjectA::ObjectA(){
}
void ObjectA::process(){
std::cout << "This is a process." << std::endl;
}
std::string ObjectA::getType(){
return "ObjectA";
}
Update
As #AlanBirtles pointed out, I've missed the public when writting the Registrar class. The code compiles but when I test it with my unit tests it doesn't seems to register ObjectA. I'm getting the out-of-range exception from the .at().
Here's what my test file looks like:
selfregisteringfactory.test.cpp
#include "catch2/catch.hpp"
#include "catch/fakeit.hpp"
#include "baseclass.h"
using namespace fakeit;
TEST_CASE( "TEST SelfRegisteringFactory class." )
{
SECTION("Test if adding an OjbjectA to the factory is possible.")
{
auto objA = DeviceCommunication::make("ObjectA");
REQUIRE(objA ->getType() == "ObjectA");
}
}

How to use custom class pointer comparator inside class being compared

I am trying to use a custom comparator as in the following minimal example:
#include <set>
using namespace std;
struct idComp;
class TestClass
{
public:
int id;
void setId(int i){ id = i; }
int getId(){ return id; }
void test( set<TestClass*, idComp> &s){
//do my stuff
}
void test2(){
set <TestClass*, idComp> s;
}
};
struct idComp
{
bool operator() (TestClass* t1, TestClass* t2) const
{
return t1->getId() < t2->getId();
}
};
int main(int argc, char* argv[])
{
return 0;
}
...but when I try to compile I get the following error relating to the test function:
comp_ref.cpp:12:34: error: ‘idComp’ was not declared in this scope
void test( set<TestClass*, idComp> &s){
^~~~~~
comp_ref.cpp:12:40: error: template argument 2 is invalid
void test( set<TestClass*, idComp> &s){
and this with the addition of test2:
/usr/include/c++/7/bits/stl_tree.h:708:31: error: invalid use of incomplete type ‘struct idComp’
_Rb_tree_impl<_Compare> _M_impl;
Any suggestions of how/where to define idComp so that it is usable by the function test?
Since you have a bit of a circular dependency, you can resolve this by forward-declaring idComp before TestClass:
struct idComp;
class TestClass
{
...
But you can leave the definition of struct idComp where it is.

invalid use of void expression in context of c++ std::function

In below code snippet while calling call back function "Invalid use of void expression" error
is flashed by the compiler.
#include <iostream>
#include <functional>
using namespace std;
template<class type>
class State {
public:
State(type type1,const std::function<void (type type1 )> Callback)
{
}
};
template <class type>
void Callback(type type1 )
{
//Based on type validation will be done here
}
int main()
{
State<int> obj(10,Callback(10));
return 0;
}
Just want to know what is the wrong here so that same can be addressed .
It seems that you want to pass the Callback<int> function itself, not its return value (which there is none), to the constructor of obj. So do just that:
State<int> obj(10, Callback<int>);
Your current code actually calls Callback(10) first and then tries to take its void "return value" to pass it to the constructor of obj. Passing void is not allowed in C++, which is why the compiler is complaining. (Callback(10) is the "void expresson" here.)
I guess this is what you want
#include <iostream>
#include <functional>
using namespace std;
template<class type>
class State {
public:
State(type type1,const std::function<void (type)> callback)
{
callback(type1);
}
};
template <class type>
void Callback(type type1 )
{
}
int main()
{
State<int> obj(10, Callback<int>);
return 0;
}
I would like to go with lambda expression approach to avoid the confusion :
#include <iostream>
#include <functional>
using namespace std;
template<class type>
class State
{
public:
State( type type1, const std::function<void (type type1 )> Callback)
{
Callback(type1);
}
};
int main()
{
State<int > monitor(10,[] ( int fault) {std::cout<<"Any Message"; });
return 0;
}

Inheriting std::stack causes an error with clang but works with gcc

Irrelevant. See update below.
I've been playing around with std::stack and noticed something strange. Here's the code:
.h file
template<typename Tp> using VecOfRef = std::vector<std::reference_wrapper<Tp>>;
template <typename T>
struct Stack : public std::stack<T,VecOfRef<T>> {};
struct Simple {
std::string txt = "txt";
};
.cpp file
int main () {
Simple smpl;
auto vec = VecOfRef<Simple>{std::ref(smpl)};
auto stdStack = std::stack<Simple,decltype(vec)>(vec); //works fine
auto myStack = Stack<Simple>(vec); //error
//to check if a reference is stored
stdStack.push(smpl);
smpl.txt.append("append");
Simple& r = sStack.top();
cout << r.txt << endl;
return 0;
}
The error message says:
19:
No matching conversion for functional-style cast from
'std::__1::vector,
std::__1::allocator > >' to
'Stack'
UPDATE:
I have been playing around with this and managed to almost get the code to work:
#include <vector>
#include <string>
#include <stack>
#include <iostream>
#include <functional>
template<typename Tp> using VecOfRef = std::vector<std::reference_wrapper<Tp>>;
template <typename T>
class Stack : public std::stack<T,VecOfRef<T>> {
public:
using std::stack<T,VecOfRef<T>>::stack;
using std::stack<T,VecOfRef<T>>::c;
T& top() {
return c.back().get();
}
};
struct Simple {
std::string txt = "txt";
void print() { std::cout << txt << std::endl; }
};
int main() {
Simple smpl;
Simple smpl_2;
Simple smpl_3;
VecOfRef<Simple> vr {smpl,smpl_2,smpl_3};
// auto myStack = Stack<Simple> (vr); // error
auto myStack = Stack<Simple> ({smpl,smpl_2,smpl_3}); // ok
auto stk = std::stack<Simple,std::vector<std::reference_wrapper<Simple>>>(vr); // ok_2
smpl.txt.append("_append");
smpl_2.txt.append("_append_2");
smpl_3.txt.append("_append_3");
myStack.top().print(); // txt_append_3
myStack.pop();
myStack.top().print(); // txt_append_2
myStack.pop();
myStack.top().print(); // txt_append
return 0;
}
It compiles under gcc but does not under clang. The error says:
Error: stack:154:43: No type named 'type' in 'std::__1::enable_if'; 'enable_if' cannot be used to disable this declaration
Line in the stack file:
Maybe the reason is that you missed a constructor
template <typename T>
struct Stack : public std::stack<T,VecOfRef<T>>
{
Stack(VecOfRef<T>){}
};
You didn't add any constructors to your Stack class.
If you want to inherit std:stack's constructors, you must specify that, using:
using std::stack<T,VecOfRef<T>>::stack; in your class.

How can I perform different actions for different template parameters in a template class?

If I want to make a template class, and depending on the typeid of the template parameter perform different actions, then how do I code this?
For instance, I have the following template class, in which I want to initialize the member field data depending on whether it is an int or a string.
#include <string>
template <class T>
class A
{
private:
T data;
public:
A();
};
// Implementation of constructor
template <class T>
A<T>::A()
{
if (typeid(T) == typeid(int))
{
data = 1;
}
else if (typeid(T) == typeid(std::string))
{
data = "one";
}
else
{
throw runtime_error("Choose type int or string");
}
}
This code would not compile however, with the following main file.
#include "stdafx.h"
#include "A.h"
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
A<int> one;
return 0;
}
The error is: error C2440: '=' : cannot convert from 'const char [2]' to 'int', which means the code is actually checking the else-if statement for an int, even though it will never be able to reach that part of the code.
Next, following this example (Perform different methods based on template variable type), I tried the following A.h file, but I got several linker errors mentioning that A(void) is already defined in A.obj.
#include <string>
template <class T>
class A
{
private:
T data;
public:
A();
~A();
};
// Implementation of constructor
template <>
A<int>::A()
{
data = 1;
}
template <>
A<std::string>::A()
{
data = "one";
}
Does anybody know how to get this code up and running? I also realize that using such an if-else statement in a template class might remove the power from a template. Is there a better way to code this?
EDIT: after discussion with Torsten (below), I now have the following A.h file:
#pragma once
#include <string>
// Class definition
template <class T>
class A
{
public:
A();
~A();
private:
T data;
};
// Implementation of initialization
template < class T >
struct initial_data
{
static T data() { throw runtime_error("Choose type int or string"); }
};
template <>
struct initial_data< int >
{
static int data() { return 1; }
};
template <>
struct initial_data< std::string >
{
static std::string data() { return "one"; }
};
// Definition of constructor
template <class T>
A<T>::A()
: data( initial_data< T >::data() )
{
}
and the following main:
#include "stdafx.h"
#include "A.h"
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
A<int> ione;
return 0;
}
The linker error I now get is: Test template 4.obj : error LNK2019: unresolved external symbol "public: __thiscall A::~A(void)" (??1?$A#H##QAE#XZ) referenced in function _wmain
Explicit specializations are the way to go.
I assume that you are including your A.h in several .cpp, and that's the root cause of your problem.
Specializations are definitions and there must be only one definition of A::A() and A::A() and so they must be in only one .cpp.
You'll have to move the explicit specialization in a .cpp
template <>
A<int>::A()
{
data = 1;
}
template <>
A<std::string>::A()
{
data = "one";
}
and keep a declaration for them in A.h
template<> A<int>::A();
template<> A<std::string>::A();
so that the compiler knows they are explicitly specialized and doesn't try to add automatic one.
Edit: with these four files, g++ m.cpp f.cpp a.cpp doesn't show any errors.
// a.h
#define A_H
#include <string>
template <class T>
class A
{
private:
T data;
public:
A();
};
template<> A<int>::A();
template<> A<std::string>::A();
#endif
// a.cpp
#include "a.h"
template <>
A<int>::A()
{
data = 1;
}
template <>
A<std::string>::A()
{
data = "one";
}
// f.cpp
#include "a.h"
int f()
{
A<int> one;
A<std::string> two;
}
// m.cpp
#include "a.h"
int f();
int main()
{
A<int> one;
A<std::string> two;
f();
}
You are correct in the second solution, what you need is template specialisation (keeping declaration and implementation together):
#include <string>
template <class T>
class A
{
private:
T data;
public:
A();
~A();
};
template <>
class A <std::string>
{
private:
std::string data;
public:
A() { data = "one"; }
};
template <>
class A <int>
{
private:
int data;
public:
A() { data = 1; }
};
If I may suggest a more elegant solution, then I would add a parameter to the constructor and avoid the template specialisation:
template <class T>
class A
{
private:
T data;
public:
A( T value ) : data( value ) {}
virtual ~A() {}
};
In case it's just the c'tor where you want to have behavior that depends on T, I would suggest to factor this out to a different struct:
template < class T >
struct initial_data
{
static T data() { throw runtime_error("Choose type int or string"); }
};
template <>
struct initial_data< int >
{
static int data() { return 1; }
}
template <>
struct initial_data< std::string >
{
static std::string data() { return "1"; }
}
If you specialize a class on it's template parameter, the different specializations are totally different types and can have different sets of data and functions.
Finally:
template <class T>
A<T>::A()
: data( initial_data< T >::data() )
{
}
kind regards
Torsten