编译时常量数组本身的编译时常量索引是编译时常量吗?

发布于 2024-07-17 13:12:55 字数 1011 浏览 6 评论 0原文

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

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

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

以另一种方式询问,

 const char v="Hello"[0];

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

我已经相信答案是否定的,但实际上一些编译器甚至没有任何警告就接受它,更不用说错误了。 例如,以下代码编译并运行时甚至没有来自 Intel 的 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!
}

但是,Microsoft 的编译器根本不会编译,并给出有关使用具有内部链接的对象的模板的相当一致的错误消息。

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

I am trying to play fancy games which have the C++ compiler synthesize hash values of constant strings at compiletime. This would let me replace the string with a single identifier, with a massive savings in code size and complexity.

For programming clarity and ease, it'd be awesome if I could examine and compute at compiletime with simple inline character strings like "Hello" which are compiletime constant pointers to compiletime constant chars.

If I can index into these at compiletime, I can make a template metaprogram to do what I want. But it is unclear if the C++ standard treats a ct-constant index of a ct-constant array as ct-constant by itself.

Asked another way,

 const char v="Hello"[0];

is quite valid C++ (and C). But is the value v a compile time constant?

I already believe the answer is no, but in practice some compilers accept it without even any warning, much less error. For example, the following compiles and runs without even a single warning from Intel's C++ compiler:

#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!
}

However, Microsoft's compiler will not compile at all, giving a reasonably coherent error message about using a template with an object with internal linkage.

I suspect the answer to my question is "No, you can't assume any array reference even to a constant array with a constant index is constant at compiletime". Does this mean the Intel compiler's successful execution is a bug in the Intel compiler?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

﹏半生如梦愿梦如真 2024-07-24 13:12:55

它也不适用于 GCC。

但是,从语言合规性的角度来看,编译器优化器确实将其视为字符常量,这很好。 我利用这一事实来允许预处理器生成的字符常量(通过使用 *#foo)。 请参阅 http://cvs.openbsd.org /cgi-bin/query-pr-wrapper?full=yes&numbers=1652,位于文件 hdr.h 中。 在我看来,有了这个宏,你可以编写

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

而不是

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

更具可读性。 :-)

It doesn't work on GCC either.

However, outside of a language-compliance viewpoint, it's nice that the compiler optimiser does treat it as a character constant, pretty much. I exploited that fact to allow preprocessor-generated character constants (by using *#foo). See http://cvs.openbsd.org/cgi-bin/query-pr-wrapper?full=yes&numbers=1652, in file hdr.h. With that macro, you could write

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

rather than

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

Much more readable, in my view. :-)

临走之时 2024-07-24 13:12:55

好问题,是的,这是可以做到的,而且符合标准,它可以在 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;
}

Good question, yes this can be done, and its fine with the standards, and it'll work on Microsoft, GCC, and Intel, problem is you have the syntax wrong :)

One second I'll cook up a sample...
Ok done, here it is. This sample is valid C++, and I've used it quite often, but indeed most programmers don't know how to get it right.

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;
}
落花浅忆 2024-07-24 13:12:55

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

更多详情请访问 boost.org

The relevant difference here is the difference between a "Integral Constant Expression" and a mere compile-time constant. "3.0" is a compile-time constant. "int(3.0)" is a compile-time constant, too. But only "3" is an ICE. [See 5.19]

More details at boost.org

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文