3

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。是否有另一种方法来获取此输出并在编译时将字符串文字转换为整数?

4

4 回答 4

3

是的,C++ 11constexpr会为您做到这一点:

 constexpr int LiteralToInt(const char * str) {
      return __COUNTER__; // or whatever.
 }
于 2012-08-03T03:31:45.427 回答
1

像这样的东西会起作用

extern const char HELLO[] = "Hello";

进而

cout << LiteralToInt<HELLO>();

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

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

于 2012-08-03T03:39:09.720 回答
1

稍微思考一下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,那么我之前的声明成立:

不 - 没有办法在编译时将字符串文字转换为整数,这样所有相同的字符串都映射到相同的值,(并且不同的字符串映射到不同的值)跨所有编译单元,缺少处理代码某种程度上来说。

于 2012-08-03T05:17:37.173 回答
0

不幸的是,我知道没有办法完全按照您的意愿行事。

您可以对琴弦施加任何限制吗?比如字符数?如果您可以将其限制为 1-8 个字符,则可以执行以下操作:

template <char Ch1, char Ch2 = '\0', char Ch3 = '\0', char Ch4 = '\0', char Ch5 = '\0', char Ch6 = '\0', char Ch7 = '\0', char Ch8 = '\0'>
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

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

于 2012-08-03T04:51:06.507 回答