2016-03-17 6 views
3

У меня есть следующее определение класса:Операторов для непримитивных штучных типов

template <typename T> 
class MyBox { 
public: 
    MyBox(T value) { _value = value; } 
    operator T() const { return _value; } 
private: 
    T _value; 
}; 

typedef MyBox<int> MyInt; 
typedef MyBox<std::string> MyString; 

Когда я пытаюсь использовать операторы на свои определениях типов, как этого

bool first = MyInt(1) == MyInt(1); // works 
bool second = std::string(MyString("a")) == std::string(MyString("a")); //works 
bool third = MyString("a") == MyString("a"); // does not compile 

компилятора жалуется на третьем сравнения

Оператор «==» не соответствует этим операндам. Типы операндов: MyString == MyString

и это происходит с любым другим, не primitve бокса (например, MyBox<float> работает, но MyBox<std::map<int,int> > не Почему это так

Это особенно для меня неясным, потому что для.? первое и второе сравнения operator T() используется - почему не может быть, что делается автоматически для MyString а

UPDATE: есть простое решение этой проблемы, кроме обеспечения конкретных операторов для каждого непримитивных шаблона? А что делать с MyString("a") == std::string("a")?

+1

@LogicStuff, замечательный материал! Спасибо, что нашел. – SergeyA

+0

Я действительно не уверен в закрытии. Дубликат объясняет «почему», но не «как исправить». – SergeyA

+0

@SergeyA Как исправить это довольно очевидно (нет 'operator ==', поэтому вам нужно написать один). Почему гораздо более интересный/трудный вопрос. – Barry

ответ

3

Причина о том, почему он работает для встроенных типов, но does't работы для пользовательских типов ответа на следующие SO quesiton: using user-defined conversions with implicit conversions in comparisons. Короче говоря, это связано с тем, что преобразование типов не происходит для типов с шаблоном. И хотя встроенный operator== для int не является шаблоном (и, следовательно, можно найти, используя преобразование типов, когда используется MyBox<int>), operator== для std::string - это шаблон.

Однако вопрос, упомянутый выше, не содержит подробностей о том, как решить эту проблему. Вот как: добавить следующие бесплатные функции

template<class T> 
bool operator==(const MyBox<T>& lhs, const MyBox<T>& rhs) { 
    return static_cast<const T&>(lhs) == static_cast<const T&>(rhs); 
} 

template<class T> 
bool operator==(const MyBox<T>& lhs, const T& rhs) { 
    return static_cast<const T&>(lhs) == rhs; 
} 

template<class T> 
bool operator==(const T& lhs, const MyBox<T>& rhs) { 
    return lhs == static_cast<const T&>(rhs); 
} 
+0

Вы правы, «как это решить?» вероятно, более важно, спасибо за это :-). Но: это нужно сделать для каждого оператора ('' <,>, <=, > =, ==,! =, .... '') Я хочу использовать, правильно? Должен ли я действительно писать '' #Operators * 3'' свободные функции, выглядящие совсем похожими? – PhilLab

+0

@PhilLab, на вопрос «почему» ответили в двух экземплярах. Я отвечаю на вопрос «как исправить эту проблему», которая, похоже, не рассматривается в дубликате. – SergeyA

+0

Интересно, почему мой ответ был подавлен, хотя. Кто-нибудь видит проблему с ним? – SergeyA

-3

Ваш второй Exemple использует operator== из std::string, строки, построенные из std::string(const std::string&)MyString::operator std::string() определяется):

bool second = std::string(MyString("a")) == std::string(MyString("a")); // cals std::string::operator==() 

Ваш третий пример не может работать: нет operator==, которая принимает два MyString S:

bool third = MyString("a") == MyString("a"); // does not compile 

Я не знаю, почему, и я изучу его, но есть специальное правило (стандарт или реализация), которые делают operator== найдено для любого параметра шаблона стручка MyBox:

#include <iostream> 
#include <string> 

template <typename T> 
class MyBox { 
public: 
    MyBox(T value) { _value = value; } 
    operator T() const { return _value; } 
private: 
    T _value; 
}; 

struct S {}; 

int main() 
{ 
    MyBox<int> zero(0), one(1); 
    std::cout << (zero == one) << std::endl; // false 

    MyBox<void*> p1(&zero), p2(&one); 
    std::cout << (p1 == p2) << std::endl; // false 

    MyBox<S> s1(S{}), s2(S{}); 
    std::cout << (s1 == s2) << std::endl; // error: no match for 'operator==' (operand types are 'MyBox<S>' and 'MyBox<S>') 
} 
+0

@SergeyA это была страшная формулировка – YSC

+1

@Barry похоже, что это связано с POD- Несс. – YSC

+1

есть ссылка на возможный дубликат. Он прекрасно объясняет, почему он работает для некоторых типов, но не для другого. Не имеет ничего общего с podness, но с шаблоном/не шаблонным характером оператора ==. – SergeyA

Смежные вопросы