【发布时间】:2014-10-26 01:24:07
【问题描述】:
提案n4121 看起来要添加std::string_literal 类型。它包含如下代码:
template<size_t n> struct string_literal { char data [n]; }
和:
template <size_t N>
constexpr int stoi( const string_literal<N>& str,
size_t* idx = 0, int base = 10);
这是我的 Number 类:
template <typename T>
struct Number
{
private:
T t;
public:
constexpr Number(const T& t)
: t(t)
{
}
constexpr Number(const std::string& s);
constexpr operator T() const
{
return t;
}
};
template <>
constexpr Number<int>::Number(const std::string& s)
: t(std::stoi(s))
{
}
我查看了How do I convert a C string to a int at compile time?,但它仅适用于 C 字符串。并且c_str() 是非常数的。最重要的是,这不包括stol、stoul、stoll、stof、stod...等等。谁知道这个提案是否会成为标准。此外,我不想等待 3 年才能发生这种库更改。我现在如何实现它?
这是我目前的尝试:
namespace lib
{
constexpr bool is_digit(char c) {
return c <= '9' && c >= '0';
}
constexpr int stoi_impl(const char* str, int value = 0) {
return *str ?
is_digit(*str) ?
stoi_impl(str + 1, (*str - '0') + value * 10)
: throw "compile-time-error: not a digit"
: value;
}
constexpr int stoi(const char* str) {
return stoi_impl(str);
}
template<size_t n> struct string_literal { char data [n]; };
template < class charT, size_t N>
constexpr string_literal<N>
make_string_literal( const charT(&arr)[N])
{
string_literal<N> sl;
for (std::size_t i = 0; i < N; ++i)
sl.data[i] = arr[i];
return sl;
}
}
template <typename T>
struct Number
{
private:
T t;
public:
constexpr Number(const T& t)
: t(t)
{
}
constexpr Number(const std::size_t N, const lib::string_literal<N>& s);
constexpr operator T() const
{
return t;
}
};
template <>
constexpr Number<int>::Number(const std::size_t N, const lib::string_literal<N>& s)
: t(lib::stoi(s.data))
{
}
int main()
{
constexpr auto s = lib::make_string_literal("123456789");
constexpr Number<int> n { sizeof(s.data), s };
return 0;
}
main.cpp:44:69: error: non-type template argument is not a constant expression
constexpr Number(const std::size_t N, const lib::string_literal<N>& s);
^
main.cpp:53:78: error: non-type template argument is not a constant expression
constexpr Number<int>::Number(const std::size_t N, const lib::string_literal<N>& s)
^
main.cpp:29:38: error: cannot initialize an array element of type 'char' with an lvalue of type 'const char [10]'
return string_literal<N>{arr};
^~~
main.cpp:60:19: note: in instantiation of function template specialization 'lib::make_string_literal<char, 10>' requested here
auto s = lib::make_string_literal("123456789");
【问题讨论】:
-
您不能直接使用
std::strings。但是,请尝试提到并链接到here 的str_const解决方案。 -
所以问题不是根据类型选择函数,而是在编译时从字符串转换为int。我认为你的标题应该反映这一点。
-
如果你的
std::string不使用字符串文字,你是如何在编译时形成的? -
当你可以推断出
N时,为什么要传递它?template<size_t N> constexpr Number(const lib::string_literal<N>& s);? -
这是我不久前用 C++14 风格 constexpr 写的东西:stackoverflow.com/a/23445223