Фон
Если в сторонней библиотеке есть такой код
class ThirdPartyClass
{
public:
int value;
ThirdPartyClass(int i) : value(i) {}
ThirdPartyClass(const std::string& s) : value(0) {}
};
bool ThirdPartyFunction(int a, const ThirdPartyClass obj)
{
return a == obj.value;
}
Тогда можно позвонить как
ThirdPartyFunction(1, 1);
ThirdPartyFunction(1, std::string("Hello, World!"));
Вопрос
Можно ли расширить эту библиотеку (без изменения стороннего кода), чтобы принять что-то вроде:
ThirdPartyFunction(1, "Hello, World!"); // const char* is not a string, implicit conversion fails
Я хочу избежать необходимости писать
ThirdPartyFunction(1, std::string("Hello, World!"));
Вышесказанное упрощено: в моем реальном примере ThirdPartyFunction
является оператором потока и ThirdPartyClass
это оболочка типа, которая позволяет взаимодействовать с потоковыми манипуляторами
Когда я начал задавать этот вопрос, я подозревал, что получить то, что я хочу, было невозможно из-за других подобных ответов SO.
К тому времени, когда я закончил задавать вопрос, я нашел обходной путь, который соответствует моим потребностям, это не совсем явное преобразование, поэтому ваш пробег может варьироваться в зависимости от того, чего именно вам нужно достичь.
Я подумал, что мог бы также опубликовать это на тот случай, если кто-то посчитает это полезным.
Работа вокруг
Добавьте следующие определения:
class MyExtension : public ThirdPartyClass
{
public:
MyExtension(const char*) : ThirdPartyClass(0) {}
};
bool ThirdPartyFunction(int a, MyExtension obj)
{
return ThirdPartyFunction(a, (ThirdPartyClass)obj);
}
Теперь можно позвонить
ThirdPartyFunction(1, "Hello, World!");
Обратите внимание, что выше можно сделать без изменения стороннего кода. Он полагается на перегрузку функции, поэтому, если вам пришлось сделать это для многих функций, это может быть неосуществимо. Вы также можете избежать наследования и просто конвертировать из MyExtension
в ThirdPartyClass
в перегруженной функции.
C ++ допускает последовательность неявных преобразований при сопоставлении аргументов с параметрами и выборе перегрузки функции. Но в последовательности допускается только одно «пользовательское» преобразование (включая вызов функции). Передача строкового литерала потребует std::string::string( char const * )
а также ThirdPartyClass::ThirdPartyClass( std::string const & )
, которые две функции. C ++ запрещает это, поскольку неограниченные преобразования замедляют работу компилятора и приводят к непредсказуемым результатам.
Вы нашли обходной путь, определив дополнительные перегрузки функций, поэтому, если это целесообразно, сделайте это: v).