C++ 编译时字符串:构造函数重载优先级介于`const char*`/`const char[]`

C++ 编译时字符串:构造函数重载优先级介于`const char*`/`const char[]`,c++,string,constexpr,compile-time-constant,constructor-overloading,C++,String,Constexpr,Compile Time Constant,Constructor Overloading,我正在尝试创建一个编译时字符串类。我从他那里得到了一些提示。不幸的是,我被困在构造函数重载优先级上:构造函数constchar[]被忽略,取而代之的是constchar*构造函数。任何提示都将不胜感激 class string { public: // Can be done compile time. Works lovely! except... template<size_t N> constexpr string(const char(&char_arr

我正在尝试创建一个编译时字符串类。我从他那里得到了一些提示。不幸的是,我被困在构造函数重载优先级上:构造函数
constchar[]
被忽略,取而代之的是
constchar*
构造函数。任何提示都将不胜感激

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.
类字符串{
公众:
//可以在编译时完成。效果很好!除了。。。
模板
constexpr字符串(const char(&char_数组)[N])
:ptr_(字符数组),长度_(N-1){}
//将调用此重写。我*必须*保留此构造函数。
字符串(常量字符*常量字符串)
:ptr_(str){
长度=strlen(str);
}
//丑陋的黑客。(不可接受)
模板
constexpr字符串(const char(&char_数组)[N],双未使用)
:ptr_(字符数组),长度_(N-1){}
私人:
常量字符*ptr_2;;
int-length;
};
constexpr const char kConstant[]=“FooBarBaz”;
constexpr字符串kString(kConstant);//错误:constexpr变量“kString”必须由常量表达式初始化(尝试调用错误的重载)
constexpr字符串kString(kConstant,1.0f);//丑陋的黑客作品。
如果我能使编译时字符串成为常量,我可以做很多很酷的事情

  • 字符串相等性测试在
    string
    上比
    const char*
  • 消除从
    const char*
    string
    的隐式转换的运行时开销,该转换调用编译时常量字符串上的
    strlen()
  • 编译时字符串集进行相等性测试,而不是对大小
这有点难看,但应该可以:

template<class T, class = std::enable_if_t<std::is_same_v<T, char>>>
string(const T * const & str)
    : ptr_(str) {
  length_ = strlen(str);
}

如果你看一看,你会发现它们甚至不需要数组,只需要指针。它们也不支持constexpr构造!这就是重点。模板化字符数组能够在编译时检测字符串大小。非模板化函数优先于模板化函数,即使它需要指针衰减。不过,我不知道如何解决这个问题。当我尝试这样做时,我自己也遇到了同样的问题,最终解决了基于可变模板的字符串。即使我注释掉
string(const char*),
编译器有问题吗?-错误:'string{((const char*)(&kConstant)),9}'不是常量expression@Slava,为我编译…令人印象深刻。我尝试了一些类似的方法,但没有指针衰减技巧就无法工作+1解释为什么
常量和
会产生不同。不幸的是,我不认为我能够得到过去的代码审查,因为它使普通的代码路径变得复杂。
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>>()) {}