Using C++ (Visual Studio). I'm trying to find a solution for converting an enum to a string. I came across X Macros (http://drdobbs.com/cpp/184401387) which seems to be a reasonable solution but I'm having a hard time getting it to work inside of a class. All the examples I've seen show everything defined outside of a class.
// ColorNames.h
X(Red, "Red"),
X(Blue, "Blue"),
...
// MyClass.h
class MyClass
{
public:
MyClass();
virtual ~MyClass();
#define X(a, b) a
enum Colors {
#include "ColorNames.h"
};
#undef X
#define X(a, b) b
char *colorNameStrings_[] = {
#include "ColorNames.h"
};
#undef X
}
The IDE chokes on the line *colorNameStrings_[] =... I guess because you can't initialize a data member variable in the header file? How do I get this to work?
The problem is that you can't initialize a non static constant inside a class definition.
You would probably have to do it like that:
// MyClass.h
class MyClass
{
public:
MyClass();
virtual ~MyClass();
#define X(a, b) a
enum Colors {
#include "ColorNames.h"
};
#undef X
static const char * colorNameStrings_[];
};
And in the .cpp file:
// MyClass.cpp
#include "MyClass.h"
#define X(a, b) b
const char * MyClass::colorNameStrings_[] = {
#include "ColorNames.h"
};
#undef X
Instead of using X-Macros, consider using the Boost.Preprocessor library. The initial, one-time definition of the code generation macros takes a bit of work, but the end result is far cleaner and much easier to reuse.
I provided a basic implementation of a generic, Boost.Preprocessor-based enum-to-string-name conversion in an answer to "How to convert an enum type variable to a string?"
Use a struct like this
struct convert
{
std::map<MyEnum, std::string> mapping;
convert()
{
mapping[SOME_ENUM_VALUE] = "SomeValue";
// etc to fill map
}
std::string operator()(MyEnum enum)
{
return mapping[enum];
}
};
Then use like this:
convert c;
std::string ret = c(myenum); //calls operator()
Related
I'm writing for a project that uses makefile rules to switch between GPU and CPU implementations. I'd like to present an interface to user code that automatically switches between implementations without having to write #ifdef GPU_MODE all over the place.
My solution had been to use a templated interface class followed by alias templates (just typedefs, really, but I like the left-to-right style) like so:
namespace INTERFACE{
template <class VERSION>
class MyClass{
public:
MyClass():theClass(){};
//more methods...
private:
VERSION theClass;
};
}
using CpuMyClass = INTERFACE::MyClass<CpuMode>; //CpuMode defined elsewhere
#ifdef GPU_MODE
using MyClass = INTERFACE::MyClass<GpuMode>;
#else
using MyClass = INTERFACE::MyClass<CpuMode>;
#endif
Thus allowing outside code to use the symbol MyClass freely, trusting it to switch between modes automatically. Unfortunately using this is proving confusing. For example, I have a second class for which I'd like to write a ctor from MyClass:
#include "MyClass.hpp"
class OutsideClass{
public:
OutsideClass(const MyClass& A);
};
This ctor triggers an "identifier 'MyClass' is undefined" error. Does anyone know what's going on here?
Did you mean something like:
struct GpuMode { };
struct CpuMode { };
namespace INTERFACE {
// ~~~~~~~~^^^^^^
template <class VERSION>
class MyClass{
public:
MyClass() : theClass(){};
//more methods..
private:
VERSION theClass;
};
}
using CpuMyClass = INTERFACE::MyClass<CpuMode>; //CpuMode defined elsewhere
#ifdef GPU_MODE
using MyClass = INTERFACE::MyClass<GpuMode>;
#else
using MyClass = INTERFACE::MyClass<CpuMode>;
#endif
class OutsideClass{
public:
OutsideClass(const MyClass& A);
};
Demo
I am wondering how I can pass a dynamically allocated array of structures from the main function to a member function of a class. I don't necessarily need to change its values in the member function, just print it.
If I do it like I would with an integer array in the following code snippet, I get that MyStruct is not defined in the MyClass.h and MyClass.cpp files. (Which makes sense)
If I include main.cpp in MyClass.h I get a lot of weird errors. Another idea was prepending struct in the member function parameter, but that lead to other errors as well.
I need to declare the struct array outside of the class, not as a member, and I cannot use STL containers.
main.cpp:
#include "MyClass.h"
int main()
{
MyClass my_class;
struct MyStruct
{
int a;
int b;
};
MyStruct* struct_array = new MyStruct[4];
// Fill struct array with values...
my_class.printStructArray(struct_array);
}
MyClass.h:
#include <iostream>
class MyClass
{
// ...
void printStructArray(MyStruct* struct_array);
};
MyClass.cpp:
#include "MyClass.h"
void MyClass::printStructArray(MyStruct* struct_array)
{
std::cout << struct_array[0].a << struct_array[0].b;
// ...
}
Just move the struct definition into MyClass.h or it's own separate header file:
MyClass.h
#include <iostream>
struct MyStruct {
int a, b;
};
class MyClass {
// ...
void printStructArray(MyStruct* struct_array);
};
The previous problem description was ambiguous, so I modified something below. Thanks.
I want to implement some macros like this:
#define AddVariable(x) \
#define x (++counter)
class Base {
private:
int counter = 0;
}
class Extend : public Base {
public:
void Handler() {
AddVariable(ASDF);
AddVariable(HJKL);
// Here may add more variables.
}
void AnotherHandler() {
// It calls ASDF, HJKL too.
}
}
The ASDF and HJKL should be available through all handlers in the cpp file, so I have to define it in the macro (it's not a good design, though). But how should I write the proper macros to achieve it (#define cannot be nested in another #define)? Or is there another better way of implementation?
Thanks in advance.
Update:
A potential implementation is
#define AddVariable(x) \
int x = ++counter;
It works, but x is not global, and I have to fix this.
It looks like you are trying to expose an incrementer to a Base object's counter to all of your functions in the .cpp file.
Answer: This is not possible.
The other functions/objects in your .cpp file do not have a reference to a Base object and thereby cannot change any of it's data.
If you want to maintain a single counter for all the Base objects you might try something like this:
class Base {
public:
static void ASDF(){counter++;}
private:
static int counter = 0;
};
This can be called from and other function:
void AnotherHandler() {
Base::ASDF();
}
EDIT:
class Base {
protected:
static int counter = 0;
};
class Another : public Base{
public:
Another(){
counter++; // As a child of Base you have access to all of it's protected variables
}
}
Would using an std::map work?
#include <iostream>
#include <map>
#include <string>
class Base {
protected:
void AddVariable(const std::string& name) {
variables[name] = counter++;
}
int& GetVariable(const std::string& name) {
return variables[name];
}
private:
int counter = 0;
std::map<std::string, int> variables;
};
class Extend : Base {
public:
void Handler() {
AddVariable("ASDF");
AddVariable("HJKL");
// May add more variables here ...
}
void AnotherHandler() {
// Use ASDF, HJKL here too
std::cout << GetVariable("ASDF") << std::endl;
std::cout << GetVariable("HJKL") << std::endl;
}
};
int main()
{
Extend e;
e.Handler();
e.AnotherHandler();
}
Output:
0
1
You cannot do that (defining a macro in a macro) with the C preprocessor.
However, sometimes you could play X-macro tricks, like here.
If you really need macro defining macros, switch to some external or non-standard preprocessor, like GNU m4 or gpp.
Alternatively, generate your C++ code with some external tool (e.g. your own Python or GNU awk script)
At last, recent GCC (e.g. GNU cpp) or Clang/LLVM offer the __COUNTER__ macro (also usable indirectly with stringification & concatenation)
I'm doing a small program, just to play with classes.
And I've made two classes, a and b.
I want to be able to access a in b and vice versa.
This is what I got so far:
#ifndef A_HH_
#define A_HH_
#include <string>
class b;
class a
{
private:
string aString;
b* bClass;
public:
a(){aString = "A";}
string getString(){return aString;}
string getBString(){return bClass->bString;}
};
#endif /* A_HH_ */
and b:
#ifndef B_HH_
#define B_HH_
#include <string>
class a;
class b
{
private:
string bString;
a* aClass;
public:
b(){bString = "B";}
string getString(){return bString;}
};
#endif /* B_HH_ */
I want to be able to access the pointer not just store it.
How can I do that?
The problem is that you use the bClass pointer in class a, for that you need the definition of class b. In this case this can be solved by simply including b.hh in a.hh. This simple solution will work as you're only declaring an a pointer (but don't access it) in the class b. A forward declaration is not enough, because it doesn't actually tells the compiler anything more than that the class b exist.
Oh, and you need to change the bClass->bString in a::getBString to bClass->getString(), as b::bString is private. And of course create an actual instance of b and assign it to bClass.
In short, to access members of a struct or a class, you need to meet two conditions:
the accessing element (class, method, ...) must have access "rights" to the referenced member
the definition of the struct/class must be available.
To overcome 1. you can either make the member public, or declare the accessing class or method as friend, or better use a getter method.
To overcome 2., you need to include the header of the referenced class.
You might use templating:
for a:
#ifndef A_HH_
#define A_HH_
#include <string>
#include "b.h"
class a
{
private:
string aString;
b* bClass;
public:
a()
{
aString = "A";
bClass = new b<a>;
}
string getString(){return aString;}
string getBString(){return bClass->getString();}
};
#endif /* A_HH_ */
and for b:
#ifndef B_HH_
#define B_HH_
#include <string>
template <typename T>
class b
{
private:
string bString;
T* aClass;
public:
b()
{
bString = "B";
aClass = new T;
}
string getString(){return bString;}
string getAString(){return aClass->getString();}
};
#endif /* B_HH_ */
This removes the circular dependency
Note: I have found the issue with how my Xcode was compiling the below and it appears unrelated to the topic discussed herein. When I have more details I will provide them here.
I recommend voting to close my question as "too localized" since it was an Xcode problem, unrelated to the c++ code itself. Many thanks for the help all the same as I did learn from the answers.
The below question (now answered and resolved) was caused by a confusing exclusion of a file from the Xcode target, thus there were no compiler errors even though the file had problems.
I have a pure virtual interface and want to define its factory method, which returns a subclass of this interface. This works fine:
struct MyVirt{
...all virtual stuff
};
class SubVirt; //forward declaration allows factory:
MyVirt*CreateClass(){
return new SubVirt;
}
Update: Some of the comments say that forward declare is not enough to achieve the above, but that's not correct. You can accomplish the above fine without the full definition of the SubVirt class.
Now, what I want to do is have a custom constructor that takes arguments. As such:
MyVirt*CreateClass(){
return new SubVirt(arg 1, etc);
}
The problem is that a class forward declaration is no longer sufficient. It needs to see the class definition or its header. This means I can either move the factory method to the file where SubVirt is defined, or I have to include that file in the above file, which creates a circular dependency.
Is there a way to forward declare the custom constructor instead? That would make it all much simpler.
Your CreateClass function looks odd, you miss () in function definition. Should be like this:
MyVirt* CreateClass()
{
return new SubVirt(arg 1, etc);
}
When return a pointer, compiler needs to know the concrete type and constructor, so forward declare is not enough.
What you could do is:
in header file: forward declare SubVirt and CreateClass function
cpp file: include MyVirt.h and define CreateClass function
Separate declaration from implementation, like everyone does.
MyVirt.h:
struct MyVirt{
...all virtual stuff
};
MyVirt.cpp:
#include "MyVirt.h"
Implementation of MyVirt
SubVirt.h:
#include "MyVirt.h"
struct SubVirt : MyVirt {
...all SubVirt stuff
};
SubVirt.cpp:
#include "SubVirt.h"
Implementation of SubVirt
Factory.h:
struct MyVirt;
MyVirt *CreateClass();
Factory.cpp:
#include "SubVirt.h"
MyVirt *CreateClass() { return new SubVirt() }
This can be accomplished by separating the declaration and implementation.
The key here is to put the definition/implementation above the includes. Suppose you want to separate the classes A and B create two files like the following:
A.hpp
#ifndef A_HPP
#define A_HPP
struct B; // fwd. decl.
struct A {
int v;
A(int v) {
this->v = v;
}
B* createB();
};
#include "B.hpp"
A* B::createA() {
return new A(v);
}
#endif A_HPP
B.hpp
#ifndef B_HPP
#define B_HPP
struct A; // fwd. decl.
struct B {
int v;
B(int v) {
this->v = v;
}
A* createA();
};
#include "A.hpp"
B* A::createB() {
return new B(v);
}
#endif // B_HPP
main.hpp
#include <A.hpp>
#include <B.hpp>
#include <iostream>
int main(int argc, char *argv[]) {
A a(42);
std::cout << a.createB()->createA()->v << std::endl;
return 0;
}
You are of course free to move the implementation into a cpp file instead. This is only the basic recipe which shows how circular dependencies can be solved even for templated classes and functions.
http://codepad.org/IsBzQANX