2014-09-19 4 views
1

Я должен отправить вам свой код, потому что я не могу выбраться из-за того, почему я получаю эту ошибку!
Я знаю, что я мог бы иметь шаблоны использования ..C++: вызов перегруженного 'basic_string()' неоднозначен

class Mappable { 
    typedef boost::variant<int, bool, unsigned short, float, char, timeval, 
      double, std::string, size_t> MultiType; 
private: 
    class Handler { 
     friend class Mappable; 
    public: 
     template<typename T> 
     operator T&() { 
      T t = 0; 
      try { 
       t = boost::get<T>(it); 
      } catch (...) { 
      } 
      return t; 
     } 
     template<class T> 
     Handler& operator=(const T& rhs) { 
      it = rhs; 
      return *this; 
     } 
    private: 
     Handler(MultiType& it, const std::string& key); 
     MultiType& it; 
    }; 
public: 
    Mappable(const std::string& tableName); 
    virtual ~Mappable(); 
    Handler operator[](const std::string& key) { 
     return Handler(map_[key], key); 
    } 
    std::string keyTypeToString(const std::string& key) { 
     std::stringstream ss; 
     ss << boost::get<T>(map_[key]); 
     return ss.str(); 
    } 
private: 
    typedef std::map<std::string, MultiType> MultiTypeMap; 
    std::string valueFromKey(const MultiTypeMap::iterator& it); 
    template<class T> 
    MultiTypeMap map_; 
}; 

/* Main.cpp */ 

int main() { 
    Mappable m; 
    m["x"] = 2; 
    m["data"] = "my data string value"; /* Correctly works */ 
    cout << (int)(m["x"]); /* Correctly works */ 
    cout << (string)(m["data"]); /* Error */ 
    cout << m.keyTypeToString<string>("data"); /* Correctly works */ 
} 

ошибок являются:

../src/data/Mappable.h:98:41: error: call of overloaded ‘basic_string(Mappable::Handler)’ is ambiguous 
../src/data/Mappable.h:98:41: note: candidates are: 
/usr/include/c++/4.6/bits/basic_string.tcc:214:5: note: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>] 
/usr/include/c++/4.6/bits/basic_string.tcc:171:5: note: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>] 
/usr/include/c++/4.6/bits/basic_string.tcc:179:5: note: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>] 

Я не могу понять, где двусмысленность!

+0

Вы говорите, что «работает», но на самом деле это не работает. Он может скомпилировать (хотя он и не должен делать этого - использовать '-pedantic -Wall -Werror'). Но он будет терпеть неудачу во время выполнения, так как вы возвращаете ссылку на локальный объект. –

+2

У вас действительно есть другие проблемы в коде, не связанные с вашими ошибками, а именно, что оператор преобразования в классе 'Handler' предназначен для преобразования в тип * reference *. Это означает, что вы возвращаете ссылку на локальную переменную, которая, несомненно, приведет к [* неопределенному поведению *] (http://en.wikipedia.org/wiki/Undefined_behavior). –

+0

No Joachim, возвращаемая ссылка - это то, что я хочу: таким образом я могу получить доступ к элементу и изменить его. –

ответ

4

У вас есть неявные преобразования для любого типа.

template<typename T> operator T&(); 

Это означает, что любой один-пары неявного конструктор для basic_string жизнеспособен (символ сопз *, станд :: строка и т.д.)

Мантра: неявных преобразований злы.

В C++ 11 вы можете добавить ключевое слово explicit к преобразованию. Это означает, что вы будете ссылаться на static_cast<>явно

template<typename T> 
    explicit operator T&() { // throws on type mismatch 
     return boost::get<T>(it); 
    } 
+0

Проклятье, я попытался вставить «явный» в конструкцию Handler, но не на «operator T &». –

+0

Я забыл следить за мантрой, спасибо! Я был близок к решению! –

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