不能创建字符串文本类型
can't make a string literal type
我想做一个字符串字面值,我可以用作模板参数。它使编译器陷入某种无限循环。问题和解决方法是什么?
template <char...> struct slit { };
template <typename ...A>
constexpr auto make_slit(char const* const s, A const ...args)
{
return *s ? make_slit(s + 1, *s, args...) : slit<args...>();
}
int main()
{
auto const tmp_(make_slit("slit"));
return 0;
}
强制性错误(含clang++ -std=c++1y
):
t.cpp:4:16: fatal error: recursive template instantiation exceeded maximum depth of 256
constexpr auto make_slit(char const* const s, A const ...args)
^
t.cpp:6:15: note: in instantiation of function template specialization 'make_slit<char, char, char, char, char, char, char, char, char, char, char, char, char, char, char,
char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char,
char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char,
char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char,
char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char,
char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char,
char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char,
char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char,
char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char,
char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char, char>' requested here
return *s ? make_slit(s + 1, *s, args...) : slit<args...>();
编辑:看看这个答案,生成编译时分隔类型是可能的。
如果不考虑循环实例化,则无法实现所需的功能,因为函数形参不能用作常量表达式,而这是模板实参所必需的。这意味着以下内容也不允许:
template <typename... A>
constexpr auto make_slit(A const... args)
{
return slit<args...>();
}
// error
make_slit('a');
如果你觉得这很奇怪,请记住constexpr函数是一个特性,它允许一些函数也可以在常量表达式中使用。然而,你的不是一般的:
char c;
std::cin >> c;
// what is the result type?
make_slit(c);
然而,我应该注意到,在设计字面值字符串操作符的过程中,有人建议允许函数模板形式(很像整数和浮点字面值),这将实现您所需要的:
// allowed...
template<char... Cs>
constexpr slit<Cs...> operator"" _slit()
{ return {}; }
// ...but only for
auto constexpr s = 123_slit;
auto constexpr t = 12.3_slit;
// ... and not
auto constexpr u = "abc"_slit;
这个缺失的功能最近在2013年由Richard Smith的n3599提出:字符串的文字操作符模板。遗憾的是,我不知道该功能的当前状态。
您可以在这里找到将字符串字元扩展为参数包的解决方案
#include <iostream>
// c++14 has it http://en.cppreference.com/w/cpp/utility/integer_sequence
namespace detail {
template <int... Is> struct seq { };
template <int N, int... Is> struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
template <int... Is> struct gen_seq<0, Is...> : seq<Is...> { };
}
constexpr size_t operator"" _len ( const char*, size_t len ){ return len; }
template < char... val > struct slit {};
#define EXPAND_STRING( type_name, str )
template <int... Is> slit< str[Is]...> make_##type_name( detail::seq<Is...> );
using type_name = decltype( make_##type_name( detail::gen_seq<str##_len>{} ) );
using Manual = slit< 'b', 'a', 'z'>;
EXPAND_STRING( MyFoo, "foo bar baz");
EXPAND_STRING( MyBar, "bla bli blo blu");
inline std::ostream& operator<<( std::ostream& os, slit<> ) { return os; }
template < char first, char... chars >
std::ostream& operator<<( std::ostream& os, slit<first,chars...> ) {
return os << first << " " << slit<chars...>{};
}
int main() {
std::cout << Manual{} << "n";
std::cout << MyFoo{} << "n";
std::cout << MyBar{} << "n";
}
EDIT:将constexpr字符串替换为自定义文本,它直接返回长度,并使用c++ 1y的轻松constexpr函数消除依赖。
相关文章:
- CRTP 单一实例不完整类型或非文本类型
- 如何从文本文件中读取数值,直到遇到字符类型?
- 如何将文本文件的特定行读取到 int 类型的数组中C++?
- 文本冒险游戏 - 如何区分一种项目类型与另一种项目类型以及如何构建项目类/子类
- 是否可以创建一个用户定义的文本,将字符串文本转换为 own 类型的数组?
- 如何使用C++将.trc文件类型转换为文本文件?
- 整数文本太大,无法用任何整数类型表示--C++
- 具有引用数据成员的结构不是文本类型吗?
- 指针类型是文本类型吗?
- FindResource 调用返回 RCDATA 类型的文本文件的 NULL
- 文本类类型成员函数约束
- 当浮点数文本直接分配给不同的类型时,编译器如何处理浮点文字?
- 如何在自由类型中获取文本宽度
- 常量表达式中的非文本类型'compare'
- C++文本整数类型
- 运行时文本类型的惊人行为
- 在C 中按行读取文本文件,每行都是不同的数据类型
- 设计具有变体字段的文本类型类,其中可以存储一个或三个对象
- (视觉-)C++ 字符串文本的模板类型推断 - VS 2010 与 VS 2017
- QString:包括非文本类型的静态数据成员的初始化