我正在编写constexpr代码,我想在编译时检查计算值。

通常的技巧是做这样的事情:


struct ReturnValue
{
    int value1;
    int value2;
};

constexpr ReturnValue doTheComputation() 
{
    return { .value1 = 10, .value2 = 20 };
}


template< auto t > struct p;

p< doTheComputation() > foo;

这给出了

implicit instantiation of undefined template 'p<ReturnValue{10, 20}>'

我可以看到结果的价值。

但是,这不适用于非结构化类型,例如std::string_viewstd::string或任何类似于字符串的类型,因为这些类型不允许是 NTTP。

不起作用的示例std::string_view: https

不起作用的示例char const *

即使我使用它char const[ some_large_numer ]来确保消息适合,就像,而不是字符串,我也会得到作为模板参数列出的 ASCII 值:

implicit instantiation of undefined template 'p<ReturnValue{{115, 111, 109, 101, 32, 115, 101, 99, 114, 101, ...}}>

是否有任何技巧或窍门可以在编译时打印非结构类型的值(作为 constexpr 函数的结果)?

我已经看到了,它显然解决了这个问题(我还没有测试过),但我正在寻找 clang 的解决方案(Xcode 15 或更新版本和 LLVM 18 或更新版本的 Apple-clang)。

10

  • 1
    无关:你可以减少return {.value1 = 10, .value2 = 20}return {10,20}


    – 


  • 1
    只需添加适当的格式化程序并使用p<std::format("{}", doTheComputation())>


    – 

  • 谢谢你的提示,有时候我需要快速的方法来计算sizeof()offsetof


    – 

  • 1
    @user12002570 如果 的定义ReturnValue很远(例如在另一个文件中),它对人类读者仍然有帮助。我更喜欢明确的定义。


    – 


  • 1
    我的意思是对于读者来说,而不是对于作者来说。比对于阅读代码的人来说return Rectangle{.width=3, .height=4};更清楚。我不是在谈论编写代码。return Rectangle{3,4}


    – 


最佳答案
1

在问题评论中提出的想法的启发,我进行了更多搜索。我发现 C++26 有一种风格,static_assert允许第二个参数是类似字符串的constexpr计算结果()。

不幸的是,即使在 C++26 中std::format也不是友好的( ),但我总是可以编写输出字符串类文字对象的格式化函数(根据规范,它只需要提供函数),所以我想出了以下解决方案:constexpr.size().data()

#include <string_view>
#include <string>

struct ReturnValue
{
    std::string_view data;
    std::string      data2;
};

constexpr ReturnValue doTheComputation() 
{
    return { .data = "some secret message", .data2 = "owned data" };
}

constexpr std::string format( ReturnValue const & val )
{
    std::string result{ val.data };
    result += ", additional data: ";
    result += val.data2;
    return result;
}

static_assert( false, format( doTheComputation() ) );

这似乎,但在 Xcode 15.4 附带的 Apple-Clang 上还不行(我仍然需要用 Xcode 16 beta 进行测试)。

总的来说,这是一个可行的解决方案,但如果有人能提出一个可以在 Xcode 15.4 上使用的解决方案,我会更高兴。

1

  • ,显然该功能不会在 Xcode 16 中实现


    –