Устранить неоднозначность оператора приведения, когда целевой класс имеет несколько конструкторов
Я пытаюсь сделать утилиту для преобразования строк, поскольку у меня плохое сочетание интерфейсов, нуждающихся в строках в различных контейнерах (char*, std::string, пользовательский тип строки) и форматах (utf-8, utf-16, utf-32), Поэтому у меня возникла идея создать оболочку с операторами приведения к различным типам. Как это:
#include <iostream>
#include <string>
struct X {
operator std::string() { return std::string("string x"); }
operator const char *() { return "zstring x"; }
};
X make_x() { return X(); }
int main()
{
std::string y = make_x(); // this works
std::string y(make_x()); // but this does not
y = make_x(); // this does not work either
y = std::string(make_x()); // nor does this, so it's about useless
std::cout << y << std::endl;
return 0;
}
Но проблема в том, что если тип преобразуется в оба char *
а также std::string
, std::string
Конструктор и присваивание будут неоднозначными между этими двумя типами. И я не хочу проходить только char *
потому что строка может быть первоначально задана диапазоном, а не как nul-terminated, требуя дополнительной копии, чтобы получить nul-завершенную, а также заставляя встроенные nuls не работать.
Так есть ли способ избавиться от них?
Важное примечание: я застрял с некоторыми компиляторами C++03, поэтому ни один оператор приведения не может быть помечен явно.
2 ответа
В итоге я создал одного помощника с оператором приведения к любому персонажу (char
, wchar_t
и либо uint16_t
или же uint32_t
в зависимости от того wchar_t
является 32 или 16-битным) типом указателя и другим помощником с оператором приведения к любой basic_string (специализированной для любого из вышеперечисленных, с использованием пользовательских черт для нестандартных типов). Это не кажется двусмысленным нигде.
Явно приведу результат make_x()
так std::string
, const char*
или что-то еще перед передачей в качестве аргумента функции, например:
std::string y(static_cast<const char*>(make_x()));
Если вам нужно сделать это много и считать это многословным, дайте операторам приведения короткие имена:
struct X {
std::string str() { return std::string("string x"); }
const char *cstr() { return "zstring x"; }
};
std::string y(make_x().str());
Если это также неприемлемо, приспособьте идиому безопасного bool к вашей цели.