C++ C+中的符号数据类型+;

C++ C+中的符号数据类型+;,c++,symbols,C++,Symbols,有些语言包含一个表示不可变符号的结构。例如,在Ruby中,符号文字的形式为::symbolName。然后,例如,可以使用它们有效地从映射中检索值(错误计数[:syntax\u errors]),而且它们可以很容易地转换为字符串(:syntax\u error.to)。我的经验是,这样可以创建可读性和可维护性都很好的代码 C++中有类似的可用性(我不想使用整型常量,因为我需要声明它们,它们不能轻易地转换成字符串;我不想在编译之前在我的源文件上运行脚本,这有一些花俏的替换)?我正在寻找使用C预处理

有些语言包含一个表示不可变符号的结构。例如,在Ruby中,符号文字的形式为:
:symbolName
。然后,例如,可以使用它们有效地从映射中检索值(
错误计数[:syntax\u errors]
),而且它们可以很容易地转换为字符串(
:syntax\u error.to
)。我的经验是,这样可以创建可读性和可维护性都很好的代码


C++中有类似的可用性(我不想使用整型常量,因为我需要声明它们,它们不能轻易地转换成字符串;我不想在编译之前在我的源文件上运行脚本,这有一些花俏的替换)?我正在寻找使用C预处理器或元模板编程的一些技巧的解决方案。

enum构造就是为此而构建的

如果您想要一个散列图,请考虑STD::unOrdEdEdmap


enum构造就是为此而构建的

如果您想要一个散列图,请考虑STD::unOrdEdEdmap


在C++11中有一个std::unordered_映射,但由于您讨论的是“符号文本”,因此使用静态符号实际上可以做得更好。简单的方法是使用直C和C预处理器

#define declare_literal(x) const char x[] = #x
declare_literal(foo); //now "foo" is a global symbol you can use everywhere
这并不能提供您可能需要的单一实例保证。这实际上比人们希望的要复杂,但你可以用一些丑陋的方式来完成:

template <typename CharType, CharType... args>
struct symbol_base {
    using self_type = symbol<CharType, args...>;
    static constexpr std::size_t char_length = sizeof...(args) / sizeof(CharType);
    static constexpr CharType value[char_length] = {CharType(args)...};
    static const std::string& as_string() { static const std::basic_string<CharType> val{value, char_length}; return val; }
    operator const std::string&() const { return as_string(); }
};

template <char... args>
using symbol = symbol_base<char, args...>;

template <wchar_t... args>
using wsymbol = symbol_base<wchar_t, args...>;
模板
结构符号库{
使用self_type=符号;
静态constepr std::size\t char\u length=sizeof…(args)/sizeof(CharType);
静态constexpr CharType值[char_length]={CharType(args)…};
static const std::string&as_string(){static const std::basic_string val{value,char_length};return val;}
运算符const std::string&()const{返回为_string();}
};
模板
使用symbol=symbol_基;
模板
使用wsymbol=symbol\u base;
因此,您可以使用以下符号制作“foo”的符号:

symbol-foo;

不是很优雅,但很有效。

在C++11中有一个std::unordered_映射,但是由于您谈论的是“符号文字”,因此使用静态符号实际上可以做得更好。简单的方法是使用直C和C预处理器

#define declare_literal(x) const char x[] = #x
declare_literal(foo); //now "foo" is a global symbol you can use everywhere
这并不能提供您可能需要的单一实例保证。这实际上比人们希望的要复杂,但你可以用一些丑陋的方式来完成:

template <typename CharType, CharType... args>
struct symbol_base {
    using self_type = symbol<CharType, args...>;
    static constexpr std::size_t char_length = sizeof...(args) / sizeof(CharType);
    static constexpr CharType value[char_length] = {CharType(args)...};
    static const std::string& as_string() { static const std::basic_string<CharType> val{value, char_length}; return val; }
    operator const std::string&() const { return as_string(); }
};

template <char... args>
using symbol = symbol_base<char, args...>;

template <wchar_t... args>
using wsymbol = symbol_base<wchar_t, args...>;
模板
结构符号库{
使用self_type=符号;
静态constepr std::size\t char\u length=sizeof…(args)/sizeof(CharType);
静态constexpr CharType值[char_length]={CharType(args)…};
static const std::string&as_string(){static const std::basic_string val{value,char_length};return val;}
运算符const std::string&()const{返回为_string();}
};
模板
使用symbol=symbol_基;
模板
使用wsymbol=symbol\u base;
因此,您可以使用以下符号制作“foo”的符号:

symbol-foo;

不完全优雅,但有效。

在C++中没有,因为编译时间和运行时间是不同的世界。< /P> 不过,您可以使用一些预处理器技巧(请参阅)。看,等等

因此,您可能有一个定义符号的文件,例如

 // file my-symbols.def
 MY_SYMBOL(a)
 MY_SYMBOL(foo)
 #undef MY_SYMBOL
您可以多次使用它,例如,一次声明某个枚举:

enum my_symbols_en {
#define MY_SYMBOL(N) sy_##N,
#include "my-symbols.def"
};
如果您不喜欢枚举,请使用类似的技巧声明不同的内容,例如静态实例

和一次,例如定义输出例程

std::ostream& operator <<(std::ostream& out, my_symbols_en symb) {
  switch (symb) {
#define MY_SYMBOL(Sy) case sy_##N: out << #Sy ; break;
#include "my-symbols.def"
  default: std::cerr << "bad symbol" << std::endl; exit(EXIT_FAILURE);
  }
  return out;
}
<代码> STD::OFSUCTORANS < P> > C++中没有,因为编译时间和运行时间是不同的世界。 不过,您可以使用一些预处理器技巧(请参阅)。看,等等

因此,您可能有一个定义符号的文件,例如

 // file my-symbols.def
 MY_SYMBOL(a)
 MY_SYMBOL(foo)
 #undef MY_SYMBOL
您可以多次使用它,例如,一次声明某个枚举:

enum my_symbols_en {
#define MY_SYMBOL(N) sy_##N,
#include "my-symbols.def"
};
如果您不喜欢枚举,请使用类似的技巧声明不同的内容,例如静态实例

和一次,例如定义输出例程

std::ostream& operator <<(std::ostream& out, my_symbols_en symb) {
  switch (symb) {
#define MY_SYMBOL(Sy) case sy_##N: out << #Sy ; break;
#include "my-symbols.def"
  default: std::cerr << "bad symbol" << std::endl; exit(EXIT_FAILURE);
  }
  return out;
}

std::ostream&运算符您考虑的是枚举类型。不幸的是,在C++中,如果你计划将它们转换成字符串,它们需要一点样板代码。是的,我不想使用枚举。我想尽可能少地声明和编写。我发现:当所有要成为符号的东西都是
const
时,这会有所帮助,但也会限制您输入符号。否
“foo”。to_sym
。然而,我认为有一种方法可以将这两种方法结合起来。让我再给你回复一下。说得清楚一点,我们想要的功能是:将字符串文字转换为“符号”,将运行时字符串转换为“符号”,将“符号”转换为字符串。最大化与现有C++的互操作性,性能/可优化性——这是符号的第一点,你在考虑枚举类型。不幸的是,在C++中,如果你计划将它们转换成字符串,它们需要一点样板代码。是的,我不想使用枚举。我想尽可能少地声明和编写。我发现:当所有要成为符号的东西都是
const
时,这会有所帮助,但也会限制您输入符号。否
“foo”。to_sym
。然而,我认为有一种方法可以将这两种方法结合起来。让我再给你回复一下。说得清楚一点,我们想要的功能是:将字符串文字转换为“符号”,将运行时字符串转换为“符号”,将“符号”转换为字符串。最大化与现有C++的互操作性,性能/可优化性——这是符号的第一点。我不想使用枚举,我正在寻找接近Ruby风格的东西。标准库中没有
std::hash_map
。我知道使用CPP和tem可以做一些令人惊奇的事情