Concat两个`const char`字符串文字

Mic*_*ann 14 c++ string-literals c-preprocessor constexpr c++11

是否可以使用constexpr?连接两个字符串文字?或者换句话说,可以在代码中消除宏,如:

#define nl(str) str "\n"

int main()
{
  std::cout <<
      nl("usage: foo")
      nl("print a message")
      ;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

更新:使用没有任何问题"\n",但我想知道是否可以constexpr用来替换这些类型的宏.

Xeo*_*Xeo 14

一点点constexpr,撒上一些TMP和指数顶部给我这个:

#include <array>

template<unsigned... Is> struct seq{};
template<unsigned N, unsigned... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>{};
template<unsigned... Is>
struct gen_seq<0, Is...> : seq<Is...>{};

template<unsigned N1, unsigned... I1, unsigned N2, unsigned... I2>
constexpr std::array<char const, N1+N2-1> concat(char const (&a1)[N1], char const (&a2)[N2], seq<I1...>, seq<I2...>){
  return {{ a1[I1]..., a2[I2]... }};
}

template<unsigned N1, unsigned N2>
constexpr std::array<char const, N1+N2-1> concat(char const (&a1)[N1], char const (&a2)[N2]){
  return concat(a1, a2, gen_seq<N1-1>{}, gen_seq<N2>{});
}
Run Code Online (Sandbox Code Playgroud)

实例.

我会更多地将它充实,但我必须开始并想在此之前放弃它.你应该可以从中工作.

  • 该示例的链接似乎已被破坏 (4认同)

ric*_*ici 1

  1. 是的,完全可以创建编译时常量字符串,并使用 constexpr 函数甚至运算符来操作它们。然而,

  2. 除了静态和线程持续时间对象之外,编译器不需要执行任何对象的常量初始化。特别是,临时对象(不是变量,并且具有小于自动存储持续时间的东西)不需要常量初始化,据我所知,没有编译器对数组这样做。请参阅 3.6.2/2-3,其中定义了常量初始化,并参阅 6.7.4 了解有关块级静态持续时间变量的更多措辞。这些都不适用于临时变量,其生命周期在 12.2/3 及后续版本中定义。

因此,您可以通过以下方式实现所需的编译时串联:

static const auto conc = <some clever constexpr thingy>;
std::cout << conc;
Run Code Online (Sandbox Code Playgroud)

但你不能让它工作:

std::cout <<  <some clever constexpr thingy>;
Run Code Online (Sandbox Code Playgroud)

更新:

但你可以让它工作:

std::cout << *[]()-> const {
             static constexpr auto s = /* constexpr call */;
             return &s;}()
          << " some more text";
Run Code Online (Sandbox Code Playgroud)

但样板标点符号太难看了,只能算是一个有趣的小技巧。


(免责声明:IANALL,虽然有时我喜欢在互联网上玩一个。所以标准中可能有一些与上述相矛盾的尘土飞扬的角落。)

(尽管有免责声明,并且在 @DyP 的推动下,我还是添加了一些更多的语言律师引文。)