2

我正在尝试玩让 C++ 编译器在编译时合成常量字符串的哈希值的花哨游戏。这将让我用单个标识符替换字符串,从而大大节省代码大小和复杂性。

为了编程的清晰性和易用性,如果我可以在编译时使用简单的内联字符串(如“Hello”)检查和计算,那将是非常棒的,这些字符串是指向编译时常量字符的编译时常量指针。

如果我可以在编译时索引这些,我可以制作一个模板元程序来做我想做的事。但尚不清楚 C++ 标准是否将 ct-constant 数组的 ct-constant 索引本身视为 ct-constant。

换个方式问,

 const char v="Hello"[0];

是非常有效的 C++(和 C)。但是va 的值是编译时间常数吗?

我已经相信答案是否定的,但实际上一些编译器在没有任何警告的情况下接受它,更不用说错误了。例如,下面的编译和运行甚至没有来自英特尔的 C++ 编译器的一个警告:

#include <iostream>
const char value="Hello"[0];
template<char c>  void printMe()
{
  std::cout << "Template Val=" << c << std::endl;
}

int main()
{
  const char v='H';
  printMe<'H'>();
  printMe<v>();
  printMe<value>(); // The tricky and interesting case!
}

然而,微软的编译器根本不会编译,给出一个合理连贯的错误信息,关于使用带有内部链接的对象的模板。

我怀疑我的问题的答案是“不,即使对具有常量索引的常量数组的任何数组引用在编译时也是常量”。这是否意味着英特尔编译器的成功执行是英特尔编译器中的一个错误?

4

3 回答 3

2

它也不适用于 GCC。

但是,在语言兼容的观点之外,编译器优化器确实将其视为字符常量,这很好。我利用这一事实来允许预处理器生成字符常量(通过使用*#foo)。请参阅文件中的http://cvs.openbsd.org/cgi-bin/query-pr-wrapper?full=yes&numbers=1652hdr.h。使用该宏,您可以编写

DECR(h, e, l, l, o)

而不是

DECR('h', 'e', 'l', 'l', 'o')

在我看来,更具可读性。:-)

于 2009-04-20T05:32:52.787 回答
1

好问题,是的,这是可以做到的,而且符合标准,它适用于 Microsoft、GCC 和 Intel,问题是你的语法错误:)

一秒钟我会做一个样品... 好的,就在这里。这个示例是有效的 C++,我经常使用它,但实际上大多数程序员不知道如何正确使用它。

template<char* MSG>
class PrintMe
{
public:
    void operator()()
    {
        printf(MSG);
    }
};

char    MyMessage[6] = "Hello"; //you can't use a char*, but a char array is statically safe and determined at compiletime

int main(int argc, char* argv[])
{
    PrintMe<MyMessage> printer;
    printer();
    return 0;
}
于 2009-04-20T07:03:27.860 回答
0

这里的相关区别是“积分常量表达式”和单纯的编译时常量之间的区别。“3.0”是一个编译时常量。“int(3.0)”也是一个编译时常量。但只有“3”是 ICE。[见 5.19]

更多详情请访问 boost.org

于 2009-04-20T09:01:13.957 回答