字符串文字作为模板参数

String Literal As Template Argument

本文关键字:参数 文字 字符串      更新时间:2023-10-16

c++的这些预处理器和模板限制正在扼杀我。目标是将字符串文字转换为整数。

template<const char* str>
inline int LiteralToInt(){
    return __COUNTER__;
}
using std::cout;
int main(){
    cout << LiteralToInt<"Hello">();
    cout << LiteralToInt<"No">();
    cout << LiteralToInt<"Hello">();
    return 0;
}

如果模板接受字符串文字,则输出为010。是否有其他方法可以获得此输出并在编译时将字符串文字转换为整数?

是的,C++11的constexpr将为您完成以下操作:

 constexpr int LiteralToInt(const char * str) {
      return __COUNTER__; // or whatever.
 }

像这样的东西可以在中工作

extern const char HELLO[] = "Hello";

然后

cout << LiteralToInt<HELLO>();

但不是文字本身。这可能不是你想要的。

正如您已经发现的,字符串文字本身不能用作模板参数。

想一想Richard J Ross III使用constexpr的答案,我找到了正确的搜索关键字。。。实际上,您所做的是在编译时对字符串进行哈希处理。您可以在C++11中(但不能在早期版本中)执行此操作,如下所示。

基本想法是使用这样的东西:

unsigned int constexpr const_hash(char const *input) { 
    // really simple hash function...
    return static_cast<unsigned int>(*input) 
         && static_cast<unsigned int>(*input) + hash(input+1); 
}

但您可能希望使用一个具有比此更健壮属性的哈希函数。。。

然而,如果你没有使用C++11,那么我之前的声明是:

否-在编译时,没有办法将字符串文字转换为整数,即在所有编译单元中,所有相同的字符串都映射到相同的值(不同的字符串映射到不同的值),而不是以某种方式处理代码。

不幸的是,我不知道该怎么做就怎么做。

你可以对字符串设置任何限制吗?喜欢多少个字符?如果你可以将其限制为1-8个字符,你可以这样做:

template <char Ch1, char Ch2 = '', char Ch3 = '', char Ch4 = '', char Ch5 = '', char Ch6 = '', char Ch7 = '', char Ch8 = ''>
struct string_hash {
    static const uint64_t value = 
        (static_cast<uint64_t>(Ch1) << 56) | 
        (static_cast<uint64_t>(Ch2) << 48) | 
        (static_cast<uint64_t>(Ch3) << 40) | 
        (static_cast<uint64_t>(Ch4) << 32) | 
        (static_cast<uint64_t>(Ch5) << 24) | 
        (static_cast<uint64_t>(Ch6) << 16) | 
        (static_cast<uint64_t>(Ch7) << 8)  | 
        (Ch8);
};

其基本上在编译时将多达8个字符填充到uint64_t中。用法如下:

const uint64_t x = string_hash<'T', 'e', 's', 't'>::value

这将创建一个编译时数值(可用于switch和所有优点),该数值对于1-8个字符长的每个字符串都是唯一的。不幸的是,唯一的缺点是你不能把它写成字符串文字,你需要把它写成char的列表