2013-08-07 2 views
4

У меня есть класс с оператором преобразования до std::string. Он отлично работает со всем, кроме функций, получающих std::basic_string<T> (с шаблоном на T).оператор преобразования с функциями шаблона

#include <string> 
struct A{ 
    operator std::string(){return std::string();} 
}; 

void F(const std::basic_string<char> &){} 
template<typename T> void G(const std::basic_string<T> &) {} 

int main(){ 
    A a; 
    F(a); // Works! 
    G(a); // Error! 
    return 0; // because otherwise I'll get a lot of comments :) 
} 

Ошибка я получаю это

error: no matching function for call to 'G(A&)'          
note: candidate is: 
note: template<class T> void G(const std::basic_string<_CharT>&) 

Теперь я знаю, что может определить G как друга в структурах A, и он будет работать, но моя проблема с большим количеством функций СТЛИ которые уже существует и получать std::basic_string<T> (например, функция operator<< печати, или оператор сравнения, или многие другие функции.

Я бы очень хотел, чтобы иметь возможность использовать A, как если бы это было std::string. Есть какой-либо способ сделать это?

+2

Проблема заключается в том, что T необходимо вывести для 'G' и что он не работает так (принимая во внимание функции преобразования). 'G (a);' будет работать, но я полагаю, это не то, что вы хотите. – jrok

+0

Да, 'G ((std :: string) a)' также работает, но оба из них на самом деле не режут его. Я хочу что-то, что будет короче/лучше, чем просто добавить функцию 'str()' member вместо оператора преобразования. – rabensky

+0

Вам лучше сделать метод ToString. –

ответ

2

Я действительно хотел бы быть в состоянии использовать, как если бы это был std::string. Есть какой-либо способ сделать это?

Да, но вы уверены, что действительно хотите этого? Решение:

struct A : public std::string { 
}; 

, но помните, что std::string не имеет virtual деструктор и, следовательно, не могут быть использованы полиморфно. Вы были предупреждены !!!

А str() является гораздо лучшим решением и позволяет быть явным, когда вы хотите передать ваши A к функции принятия std::basic_string<T>.

+0

Это действительно интересный вариант. Я не намерен использовать его полиморфно, и, честно говоря, это не совсем то, что я хочу/нуждаюсь - но мне придется подумать, может быть, я смогу заставить его работать! ** Редактировать ** - можно ли наследовать его из 'const std :: string'? – rabensky

+0

@cluracan вы не можете наследовать от «const» что-то. –

+0

@NeilKirk - слишком плохо :(потому что это именно то, что я хотел бы здесь ... (возможно, еще не думал об этом до конца) – rabensky

2

Компилятор не может сделать так далеко; вы либо должны явно вызвать оператор приведения или Явно указать параметр шаблона:

G(static_cast<std::string>(a)); 
G<char>(a); 

Чтобы понять, почему компилятор не может сделать и определяемые пользователем преобразования и аргумент шаблона вывод, давайте рассмотрим следующий пример:

template<typename T> 
struct Number { 
    Number(double n) {}; 
    Number(int n) {}; 
}; 

struct A{ 
    operator Number<double>(){return Number<double>(1.);} 
    operator Number<int>(){return Number<int>(1);} 
}; 

template<typename T> void G(Number<T>& number) { } 

int main(){ 
    A a; 
    G(a); // What do I do ?! 
    return 0; 
} 

Что должен делать компилятор в этом случае?

+1

Но оба этих параметра хуже (уродливее), чем использование определенной функции 'str()' для преобразования. Таким образом, в реальном смысле этот недостаток делает операторы преобразования практически бесполезными (для таких шаблонов, как 'string'). Разве это не так? – rabensky

+0

О вашем редактировании - не очень хороший пример. Теперь есть 2 варианта, и компилятор должен сказать «эй, есть два варианта!» как это всегда бывает, когда есть два варианта (даже для материалов без шаблонов и конверсий, которые работают полностью как 'int' и' long'). Проблема в том, что, хотя в моем случае есть опция, компилятор находит 0 опций. – rabensky

+0

@cluracan Для компилятора просто недостаточно ограничений для выполнения простого одноуровневого вывода. И заставить компилятор сделать вывод нескольких уровней будет иметь множество побочных эффектов. – zakinster

1

Определения, определенные пользователем, не принимаются во внимание при выводе аргумента шаблона.

Явная специализация G будет работать.

G<char>(a); 
Смежные вопросы