Устранить неоднозначность оператора приведения, когда целевой класс имеет несколько конструкторов

Я пытаюсь сделать утилиту для преобразования строк, поскольку у меня плохое сочетание интерфейсов, нуждающихся в строках в различных контейнерах (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 к вашей цели.

Другие вопросы по тегам