【发布时间】:2016-07-03 19:11:44
【问题描述】:
这发生在很多人身上,也发生在我身上。我一直在玩 C++ 中的编译时字符串。
我决定采用显然无法使用的方法:使用 template <char...> 类。
这是我想出来的,很常见,没什么特别的,而且也不管用。
template <char... chars> class string
{
public:
static constexpr const char value[] = {chars...};
constexpr string()
{
}
constexpr operator decltype(value) & () const
{
return value;
}
};
template <char... chars> constexpr const char string <chars...> :: value[];
我的想法是制作一个 string 实例 constexpr 可构造并公开某种 constexpr 转换,以便提供其内容。
现在,如果我这样做了
static constexpr const char x[] = "ciao";
template <const char * str> void print()
{
std :: cout << str << std :: endl;
}
print <x> ();
这有效并且说ciao。如果我这样做,我也会得到ciao
std :: cout << string <'c', 'i', 'a', 'o'> {} << std :: endl;
或
print <string <'c', 'i', 'a', 'o', '\0'> :: value> ();
但是当我这样做时
print <string <'c', 'i', 'a', 'o', '\0'> {}> ();
我得到:No matching function for call to print。
我肯定错过了一些东西。做我想做的事是不可行的吗?使实例执行 constexpr 强制转换以某种方式返回 value?如果可行,我将能够在编译时轻松地进行运算符和字符串操作,“唯一”的缺点是超无聊的'i', 'n', 'i', 't', 'i', 'a', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n'。
进一步的实验
我做了另一个完美的实验。
template <char... chars> class string
{
public:
constexpr string()
{
}
constexpr operator size_t () const
{
return sizeof...(chars);
}
};
template <size_t length> void print()
{
std :: cout << length << std :: endl;
}
print <string <'c', 'i', 'a', 'o'> {}> ();
它会打印出漂亮的4。
【问题讨论】:
-
我认为那是因为您使
operator()仅可调用左值(只是编造的),因此从临时调用它不能也不会编译。 :) -
我猜这与推断
print的类型名有关。我对何时无法推断类型没有充分的了解。 SO中的许多人都这样做。如果这是问题所在,希望他们中的一个能够解释它。 -
@MatteoMonti:没错,没关系!
-
据我所知,您的代码在 C++17 中很好,但在 C++14 中不行。您的附加实验在 C++14 中很好,因为它使用了一个完整的非类型模板参数;此类参数的模板参数不像 C++14 和 11 中的指针那样受限制(它们允许转换的常量表达式)。 This answer 有一些相关信息。问题是,Clang 似乎是目前唯一实现了 C++17 更新规则的编译器(3.8.0 在 C++1z 模式下按预期编译您的代码)。
-
有什么理由必须使用
template <const char * str> void print()而不是字符串<...>?
标签: c++ templates char constexpr