我想在编译时使用类型的名称.例如,假设我写了:
constexpr size_t my_strlen(const char* s)
{
const char* cp = s;
while(*cp != '\0') { cp++; };
return cp - s;
}
Run Code Online (Sandbox Code Playgroud)
现在我希望:
template <typename T>
constexpr auto type_name_length = my_strlen(typeid(T).name());
Run Code Online (Sandbox Code Playgroud)
但是,唉,typeid(T).name()只是const char*,而不是constexpr ......还有其他一些constexpr方法来获得一个类型的名字吗?
enumC++中的类型是相当基本的; 它基本上只是为标签创建了一堆编译时值(可能具有适当的范围enum class).
将相关的编译时常量分组在一起非常有吸引力:
enum class Animal{
DOG,
CAT,
COW,
...
};
// ...
Animal myAnimal = Animal::DOG;
Run Code Online (Sandbox Code Playgroud)
然而,它有各种各样的缺点,包括:
在这篇文章中,我试图创建一种解决这些缺点的类型.
一个理想的解决方案采用常量的编译时知识及其与字符串的关联的概念,并将它们组合成一个类似于scoped-enum的对象,可以通过enum id和enum string name进行搜索.最后,结果类型将使用尽可能接近枚举语法的语法.
在这篇文章中,我将首先概述其他人为各个部分所尝试的内容,然后介绍两种方法,一种完成上述方法,但由于静态成员的初始化顺序而具有未定义的行为,另一种解决方案不那么漂亮语法但由于初始化顺序没有未定义的行为.
关于获取枚举中的项目数量(1 2 3)以及网上提出的大量其他问题(4 5 6)等,有很多问题.而且普遍的共识是,没有确定 -火的方式做到这一点.
仅当您强制执行枚举值为正且增加时,以下模式才有效:
enum Foo{A=0, B, C, D, FOOCOUNT}; // FOOCOUNT is 4
Run Code Online (Sandbox Code Playgroud)
但是,如果您尝试编码某种需要任意值的业务逻辑,则很容易被破坏:
enum Foo{A=-1, B=120, C=42, D=6, FOOCOUNT}; // ????
Run Code Online (Sandbox Code Playgroud)
所以Boost的开发人员试图用Boost.Enum来解决这个问题,Boost.Enum使用了一些相当复杂的宏来扩展到一些至少会给你大小的代码.
在迭代枚举中有一些尝试; 可以迭代的类似枚举的对象,理论上允许隐式大小计算,甚至在[7](7 8 9,...)的情况下明确允许
尝试实现这一点通常会导致自由浮动函数和使用宏来适当地调用它们.(8 …
假设您要生成标识符和字符串的匹配列表
enum
{
NAME_ONE,
NAME_TWO,
NAME_THREE
};
myFunction(NAME_ONE, "NAME_ONE");
myFunction(NAME_TWO, "NAME_TWO");
myFunction(NAME_THREE, "NAME_THREE");
Run Code Online (Sandbox Code Playgroud)
..没有重复自己,没有自动生成代码,使用C/C++宏
初步猜测:
您可以添加包含的#include文件
myDefine(NAME_ONE)
myDefine(NAME_TWO)
myDefine(NAME_THREE)
Run Code Online (Sandbox Code Playgroud)
然后使用它两次,如:
#define myDefine(a) a,
enum {
#include "definitions"
}
#undef myDefine
#define myDefine(a) myFunc(a, "a");
#include "definitions"
#undef myDefine
Run Code Online (Sandbox Code Playgroud)
但#define不允许你在字符串中放置参数?
我试图实现一个enum class行为类似于C++ 11(具有类型安全性等)引入的行为,但它也表现为一个真正的类(使用构造函数,方法等).为了做到这一点,我保持内部enum匿名:这有副作用,为了保持m_value作为private成员变量,我不得不添加一个static名为的成员变量_,如下所示:
#include <iostream>
#include <experimental/string_view>
class State
{
public:
static enum
{
UNKNOWN,
STARTED,
STOPPED
} _;
private:
using Type = decltype( _ );
Type m_value;
public:
constexpr State( Type value = UNKNOWN )
: m_value( value )
{ }
constexpr bool operator==( Type value ) const
{
return m_value == value;
}
constexpr std::experimental::string_view to_string( ) const
{
switch ( m_value )
{ …Run Code Online (Sandbox Code Playgroud) 考虑一下,我有以下enum课程:
enum class TestEnum
{
None = 0,
Foo,
Bar
};
Run Code Online (Sandbox Code Playgroud)
我想指定ostream operator ( << )这个enum类,所以我可以写:
std::cout << "This is " << TestEnum::Foo;
Run Code Online (Sandbox Code Playgroud)
并得到以下输出This is Foo。
我的问题是:
是否有存储枚举“名称说明符”的地方?(即对于enum class TestEnum 来说,它是None,Foo和Bar)所以我可以编写一个函数(或最多是函数模板)来指定ostream运算符,如下所示TestEnum:
std::ostream& operator<< ( std::ostream& os, TestEnum aEnum ) {
return std::string( aEnum.name() );
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,我是这样做的:
std::ostream& operator<< ( std::ostream& os, TestEnum aEnum ) {
switch( aEnum ) …Run Code Online (Sandbox Code Playgroud) 这个问题很可能是"如何将字符串映射到枚举"的第n次迭代.
我的要求更进一步,throw当在有效输入范围内找不到密钥时,我想要一个例外.所以我有这个实现EnumMap(需要提升const std::map定义):
#include <map>
#include <string>
#include <sstream>
#include <stdexcept>
#include <boost/assign.hpp>
typedef enum colors {
RED,
GREEN,
} colors;
// boost::assign::map_list_of
const std::map<std::string,int> colorsMap = boost::assign::map_list_of
("red", RED)
("green", GREEN);
//-----------------------------------------------------------------------------
// wrapper for a map std::string --> enum
class EnumMap {
private:
std::map<std::string,int> m_map;
// print the map to a string
std::string toString() const {
std::string ostr;
for(auto x : m_map) {
ostr += x.first + ", ";
} …Run Code Online (Sandbox Code Playgroud) 我试图通过遍历枚举创建一副扑克牌Suit和Rank(我知道有没有遍历枚举好办法,但我没有看到另一种).我通过enum_count在每个枚举的末尾添加一个枚举器来做到这一点,其值用于表示枚举的长度和结尾.
#include <vector>
using namespace std;
enum class Suit: int {clubs, diamonds, hearts, spades, enum_count};
enum class Rank: int {one, two, three, four, five, six, seven, eight,
nine, ten, jack, queen, king, ace, enum_count};
struct Card {
Suit suit;
Rank rank;
};
class Deck{
vector<Card> cards{};
public:
Deck();
};
Deck::Deck() {
// ERROR ON THE BELOW LINE
for (Suit suit = Suit::clubs; suit < Suit::enum_count; suit++) {
for (Rank rank = Rank::one; rank < …Run Code Online (Sandbox Code Playgroud) 我有类的风格Class1(见代码).枚举和函数从枚举中获取所有值.值(FOO_1,FOO_2等)从类到类别以及值(数量不同sizeof(Foos)).我调用该函数一次拿到的sizeof枚举,备用内存和与第二呼叫我想所有的值*pFoos(2,1,6在示例代码中).有没有更好的方法然后使用包含所有值的数组(size_t arr[3] ={FOO_1 , FOO_X, FOO_BAR })?
class Class1{
enum Foos{
FOO_1 = 2,
FOO_X = 1,
FOO_BAR = 6
}
};
Class1::GetFoos(size_t* pFoos, size_t* pSize)
{
size_t len = sizeof(Foos);
if (len > *pSize)
{ //Call function once to get the size
*pSize= len ;
return -1;
}
for(size_t i = 0; i< *pSize; i++)
{
//copy all enum values to …Run Code Online (Sandbox Code Playgroud) 我需要一个没有宏魔法的通用模板类,我可以像这样使用:
template<typename E>
class enum_operators
{
E& operator++( E& orig )
{
orig = static_cast< E >( orig + 1 );
return orig;
}
};
enum colors : public enum_operators< colors >
{
white,
red,
green,
blue
};
enum corners : public enum_operators< corners >
{
topleft,
topright,
bottomleft,
bottomright
};
Run Code Online (Sandbox Code Playgroud)
是否可以使用可变参数模板或其他东西?我怎样才能做到这一点?
我在谷歌上搜索如何迭代枚举,发现了各种建议,例如 如何迭代枚举? 尽管所有这些方法都必须导致迭代整数,但我发现建议的解决方案或多或少是一种黑客行为。是否有更深层的原因导致此操作没有得到更好的支持;或者从另一方面来看,哪个更可移植(包括C和C++之间的一个)并且更符合标准?