I have a class like this:
class TType {
public:
...
enum binary_type {
bt_a = 0,
bt_xyz,
....
bt_ak = 10,
....
};
}
and I use it in several places, also the enum:
if(var12 == TType::bt_a ) { ....
Now I imported a C library which has exactly the same enum (same keys, same values, same size) inside one of it's headerfiles:
typedef enum data_types_e {
bt_a = 0,
bt_xyz,
....
} data_types;
How can I define the enum in the c++ class definition to use the declaration of the c headerfile?
I want to continue using the enum the same way as before (TType::bt_a), and avoid copying the whole enum. Furthermore I don't wont to modify the library (otherwise a preprocessor-macro would do the trick) and I want changes made in the library also be made to the enum in my class.
Neither a typedef inside the c++ class definition nor a type alias (c++11) seem to work in this situation.
"How can I define the enum in the c++ class definition to use the declaration of the c headerfile?"
You can simply reuse the values from the c-style enum:
#include "TheOtherEnum.h"
...
enum binary_type {
bt_a = ::bt_a,
bt_xyz = ::bt_xyz,
....
bt_ak = ::bt_ak,
....
};
"Neither a typedef inside the c++ class definition nor a type alias (c++11) seem to work in this situation."
Yes these would work to provide the correct enum type, but you'll still need to qualify the values from the global namespace and not for nested to your class.
You can make C++ enum dependant of C enum:
typedef enum data_types_e {
bt_a = 0,
bt_xyz,
....
} data_types;
// ...
class TType {
public:
...
enum binary_type {
bt_a = bt_a,
bt_xyz = bt_xyz,
....
};
}
If possible, try renaming your class TType say, class TType_1.
//=============CLibraryFileContainingEnum.h=================
typedef enum data_types_e
{
bt_a = 9999,
bt_xyz
} data_types;
//==========================================================
//==========================================================
class TType_1
{
public:
enum binary_type
{
bt_a = 8878,
bt_xyz
};
};
namespace TType
{
#include "CLibraryFileContainingEnum.h"
}
int main()
{
int a = TType::bt_a; //this prints 9999
cout << a << endl;
return 0;
}
//==========================================================
Here is my answer, this is an old topic, but better lately than never
class TType {
public :
public:
...
#undef __cplusplus
#include "yourheaderc.h"
#define __cplusplus
}
maybe with a typedef binary_type data_types to preserve your nominations
But this solution is available if your header don't contains syntax C forbidden in C++. I'm currently searching a new solution because there are prototypes in my header that contains something like :
void afunction( unsigned long id,
enum T_TYPE type,
enum T_CHAR characteristic,
unsigned short number,
unsigned short value);
because T_TYPE and T_CHAR are not typedef-ed but this syntax is non-sense in C++ because it's the declaration syntax. So my solution is not appropriate if you are in a similar case.
Related
I'm trying to explore "using" in C++, and currently I would like to convert typedef into using.
For example,
typedef enum tag_EnumType : int {
A,
B,
C,
} EnumType;
And I tried to convert it as following
using EnumType = enum tag_EnumType : int {
A,
B,
C,
};
However, the compilation failed. Could anyone help? Thanks in advance.
The truth is, I'm working on a giant project. Some of typedef enum could be rewritten as using, but others couldn't. Does anyone know the reason? Is it related with namespace or sth?
typedef enum is a C way of creating enums. If you want it the C++ way, you better write:
enum EnumType : int {
A,
B,
C,
};
In C++11 and above, scoped enums are also available, that way you prevent name collisions.
enum class EnumType : int {
A,
B,
C,
};
using statements are for other typedefs, some examples:
using IntVector = std::vector<int>;
using Iterator = IntVector::Iterator;
using FuncPtr = int(*)(char, double);
Due to my inability to find an answer or the right words to search for I ask here:
I have a (lengthy) class enum defined by
enum class SomeLongName { Foo = 1, Bar = 7, FooBar = 42 };
The only way I know to define a vector of those is:
#include <vector>
enum class SomeLongName { Foo = 1, Bar = 7, FooBar = 42 };
int main() {
std::vector<SomeLongName> v1 = {
SomeLongName::Foo,
SomeLongName::FooBar
};
return 0;
}
Is there a way (alternative abbreviated syntax) to use a class enum and don't need to rewrite SomeLongName:: for each value independently? e.g. something like (not working)
#include <vector>
enum class SomeLongName { Foo = 1, Bar = 7, FooBar = 42 };
int main() {
std::vector<SomeLongName> v1 = (SomeLongName::) { Foo , Bar };
return 0;
}
In case this matters: I am using MSVC 2019, amd64 (64bit), C++17 on windows 10 64bit
Note: using a typedef like suggested in this stackoverflow discussion thread is not actually what I want or am asking for
C++20 added using enum X syntax, which does what it looks like.
#include <vector>
enum class SomeLongName { Foo = 1, Bar = 7, FooBar = 42 };
int main()
{
using enum SomeLongName;
std::vector<SomeLongName> v1 = { Foo, Bar };
return 0;
}
In previous versions, you can use an enum instead of an enum class.
Pre C++20: Unfortunately no. Its a "feature" of scoped enums that you have to prepend the name of the enum type. However, before scoped enums were a thing, it was common to wrap enums in a class to avoid polluting the namespace. You can still do that:
#include <vector>
struct SomeLongName {
enum values { Foo = 1,Bar = 7, FooBar = 42};
static std::vector<values> make_vect() {
return {Foo,FooBar};
}
};
int main() {
auto v = SomeLongName::make_vect();
}
It's not "nice" but it works.
Past C++20: I refer you to this answer.
I'm using C++ with GCC's C extension for designated inits / designated array initializers and I've come across a bit of a pickle. If I have the following (contrived) example code,
#include <string>
#include <string_view>
struct STRUCTURE {
enum class ENUM { A, B, C };
static constexpr std::string_view STRINGS[] {
[static_cast<int>(ENUM::A)] = "A",
[static_cast<int>(ENUM::B)] = "B",
[static_cast<int>(ENUM::C)] = "C"
};
constexpr std::string_view operator[](ENUM e) const {
return STRINGS[static_cast<int>(e)];
}
};
Everything works as expected. However, if I now template the structure, i.e.
#include <string>
#include <string_view>
template <typename T>
struct STRUCTURE { /*same structure definition*/ };
I get a compile-time error that the C99 designator initializers I have are not integral constant expressions.
In fact, in some cases with namespaces I get an internal compiler error / internal compiler segfault, leading me to believe this is an internal issue, but I cannot confirm such.
If I move the scoped enum class outside of the template, everything works again. In that manner, I can simply add a level of indirection to my actual code, however I would prefer not doing so.
Here is a godbolt with a macro allowing you to change between the templated and non-templated definition, and a simple main printing out one of the strings.
Even odder: Say I change the type of the internal array to ints. I.e,
struct STRUCTURE {
enum class ENUM { A, B, C };
static constexpr int INTS[] {
[static_cast<int>(ENUM::A)] = 65,
[static_cast<int>(ENUM::B)] = 66,
[static_cast<int>(ENUM::C)] = 67
};
constexpr int operator[](ENUM e) const {
return INTS[static_cast<int>(e)];
}
};
I have the same issue. But now if I assign the values via static casts of the enum as the designators are, i.e,
...
static constexpr int INTS[] {
[static_cast<int>(ENUM::A)] = static_cast<int>(ENUM::A),
[static_cast<int>(ENUM::B)] = static_cast<int>(ENUM::B),
[static_cast<int>(ENUM::C)] = static_cast<int>(ENUM::C)
};
...
This works, template or not. Godbolt for this, too.
I have many types of game-object that are related together is some ways.
All relations is implemented by Map<K1,K2>.
#include <vector>
using namespace std;
template<class K1,class K2> class Map{ //N:N relation
public: std::vector<K2*> getK2(K1* k1){/* some code */return std::vector<K2*>();}
public: std::vector<K1*> getK1(K2* k2){/* some code */return std::vector<K1*>();}
//... various function ...
};
Here is the hub class GameRelation that facilitates all relation query :-
(just an example, no need to pay attention to all detail)
class Human{}; class House{}; class Dog{};
class GameRelation{
public:
#define RELATION(A,B,EnumName) Map<A,B> Map##EnumName; \
enum EnumName##Enum{EnumName}; \
std::vector<B*> getAllRight(EnumName##Enum e,A* a){ \
return Map##EnumName.getK2(a); \
}
//... various function ...
RELATION(Human,House,Own)
//I can insert any relation that I want
};
The above macro expands into something like :-
Map<Human,House> MapOwn;
enum OwnEnum{Own};
std::vector<House*> getAllRight(OwnEnum e,Human* a){
return MapOwn.getK2(a);
}
Here is how it can be used (full demo):-
int main() {
GameRelation gameRelation;
std::vector<House*> houses=gameRelation.getAllRight(GameRelation::Own,new Human());
//get all "House" that is "Own" by a "Human"
return 0;
}
After some testing, it works good. Everyone is happy with the magical result.
However, my conscious tell me that it is a hack.
It is also a little bad for content-assist (e.g. intellisense) and automatic refactoring.
I also need the awesome hacking X-MACRO if I want to move their implementation to .cpp.
Question:
Is there any elegant (less hack) way? What is it?
"No" can be a valid answer.
Is X-MACRO the (professional) way to go when I need such (strange) feature?
struct GameRelation{
template <typename A, typename B>
struct Relation {
std::vector<B*> getAllRight(A* a) {
return map.getK2(a);
}
private:
Map<A, B> map;
};
Relation<Human, House> own;
};
int main() {
GameRelation gameRelation;
std::vector<House*> houses = gameRelation.own.getAllRight(new Human());
}
! i'm working on a gun template,it should be like this:
template <Bullet>
class gun
{
};
that Bullet is a class that will define in other file,my question is how i can use this bullet in gun as a type? how can i use a class as a template in other class? i want a little bit long explanation!
thanks...!
this is what i tried to do:
#include "Bullet.h"
#include <iostream>
using namespace std;
#define BulletWeapon1 100
#define BulletWeapon2 30
#define BulletWeapon3 50
enum Weapons
{
Gun1,Gun2,Gun3
}CurrentWeapon;
template <class T=Bullet>
class Gun
{
};
int main()
{
return 0;
}
If you need only need the Bullet class inside gun, then you can just don't use a template:
class gun {
Bullet x;
// ...
};
otherwise, if you want to allow any class but provide a default class Bullet, you can use:
template <class T = Bullet>
class gun {
T x;
// ...
};
In particular, if you want to make sure that T is always a base class of Bullet, you can play around with type traits such as std::enable_if and std::is_base_of.
On a side note, please try to avoid statements like using namespace std; and begin getting used to the std:: prefix instead. It will save you some headaches when you'll have problems of multiple definitions or weird look ups.
Also, try to avoid #defines as well. This:
#define BulletWeapon1 100
#define BulletWeapon2 30
#define BulletWeapon3 50
can be converted to:
const int BulletWeapon1 = 100;
const int BulletWeapon2 = 30;
const int BulletWeapon3 = 50;
Finally notice that in C++11 you can use enum classes which are a little bit more type safe than simple enums:
enum Weapons { Gun1,Gun2,Gun3 } CurrentWeapon;
can become:
enum class Weapons { Gun1, Gun2, Gun3 } CurrentWeapon = Weapons::Gun1;