[英]Compile-time strings: constructor overload precedence between `const char *` / `const char[]`
我正在尝试制作一个编译时字符串类。 我从这篇文章中得到了一些提示。 不幸的是,我被困在构造函数重载优先级上: const char[]
构造函数被忽略,而有利于const char*
构造函数。 任何提示将不胜感激!
class string {
public:
// Can be done compile time. Works lovely! except...
template<size_t N>
constexpr string(const char(&char_array)[N])
: ptr_(char_array), length_(N-1) {}
// This override gets called instead. I *must* keep this constructor.
string(const char* const str)
: ptr_(str) {
length_ = strlen(str);
}
// Ugly hack. (not acceptable)
template<size_t N>
constexpr string(const char(&char_array)[N], double unused)
: ptr_(char_array), length_(N-1) {}
private:
const char* ptr_;
int length_;
};
constexpr const char kConstant[] = "FooBarBaz";
constexpr string kString(kConstant); // Error: constexpr variable 'kString' must be initialized by a constant expression (tries to call wrong overload)
constexpr string kString(kConstant, 1.0f); // ugly hack works.
如果我可以制作编译时字符串常量,我可以做很多很酷的事情。
string
比const char *
strlen()
从const char *
到string
的隐式转换的运行时开销。这有点难看,但它应该可以工作:
template<class T, class = std::enable_if_t<std::is_same_v<T, char>>>
string(const T * const & str)
: ptr_(str) {
length_ = strlen(str);
}
诀窍在于,在模板参数推导期间,通过 const 引用获取指针会阻止数组到指针的衰减,因此当您传递数组时,编译器无法推导出T
并且会忽略构造函数。
缺点是这也会拒绝其他可以隐式转换为const char *
。
另一种方法可能是接受可转换为const char *
所有内容,然后根据所述事物是否为数组进行调度。
template<size_t N>
constexpr string(const char(&char_array)[N], std::true_type)
: ptr_(char_array), length_(N-1) {}
string(const char * str, std::false_type)
: ptr_(str) {
length_ = strlen(str);
}
template<class T, class = std::enable_if_t<std::is_convertible_v<T, const char *>>>
constexpr string(T&& t)
: string(std::forward<T>(t), std::is_array<std::remove_reference_t<T>>()) {}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.