Оператор преобразования не будет компилироваться в Visual Studio 2013, но успешно компилируется с помощью gcc

Следующий код успешно компилируется с помощью gcc, но не компилируется в Visual Studio 2013:

#include <memory>
#include <iostream>

using namespace std;

template <typename T>
class MyClass {
public:
    MyClass(T* ptr) : m_ptr(ptr) {}

    // All of the errors are caused by this conversion operator:
    // =========================================================
    template <typename U>
    operator typename std::shared_ptr<U>() const & {
        return m_ptr;
    }
    //==========================================================

private:
    shared_ptr<T> m_ptr;
};

int main(int argc, char* argv[]) {
    MyClass<int> c(new int(42));

    shared_ptr<int> ptr = c;
    cout << *ptr << endl;
}

Я совершенно уверен, что это ошибка в компиляторе VS2013, потому что он компилируется в более новых версиях Visual Studio, но проблема в том, где я работаю, мы застряли с использованием VS2013. Заставить их сменить компилятор не может быть и речи. (Мы должны использовать тот же компилятор, который использует поставщик, поставляющий наше программное обеспечение, и они используют VS2013.)

Ошибки перечислены ниже:

Error   1   error C2143: syntax error : missing ';' before '&'  
Error   2   error C2238: unexpected token(s) preceding ';'  
Error   3   error C2988: unrecognizable template declaration/definition 
Error   4   error C2059: syntax error : '<end Parse>'   
Error   5   error C2334: unexpected token(s) preceding ':'; skipping apparent 
Error   6   error C1004: unexpected end-of-file found   

Мой вопрос, даже с ограничениями VS2013, есть ли какой-либо обходной путь, чтобы этот код скомпилировался и успешно запустился?


person tjwrona1992    schedule 31.07.2018    source источник
comment
Рекомендую разметить код, чтобы указать, где ошибки.   -  person user4581301    schedule 01.08.2018
comment
@user4581301 user4581301, я окружил участок кода, вызывающий ошибки, комментарием. Ошибки в целом очень не описательные и мало помогают.   -  person tjwrona1992    schedule 01.08.2018
comment
Я думаю, что есть обман для этого, пытаясь найти его. Код должен компилироваться с operator std::shared_ptr<U>() const &, так как typename не нужен.   -  person NathanOliver    schedule 01.08.2018
comment
Работает на меня. Расположение большинства из них было довольно легко определить, так как в коде есть только один &, но каждая мелочь помогает.   -  person user4581301    schedule 01.08.2018
comment
@NathanOliver, я только что попробовал, и он все еще не компилируется. :( Есть похожие вопросы о том, как это не работает в Visual Studio 2013, но ответ всегда таков, что это ошибка в компиляторе, и никто явно не спрашивал, есть ли обходной путь, чтобы заставить его работать с этой версией компилятора. .   -  person tjwrona1992    schedule 01.08.2018
comment
@tjwrona1992 Похоже, это. Обходного пути нет, кроме как не использовать квалификатор ссылки.   -  person NathanOliver    schedule 01.08.2018
comment
Независимо от того, является ли это действительным C++, попытка вернуть подобную константную ссылку, когда возможно временное преобразование, только вызывает мир боли и неопределенного поведения при малейшей провокации. Краткая версия: не делайте этого.   -  person Sam Varshavchik    schedule 01.08.2018
comment
@NathanOliver, ааа, хорошо, это решает этот случай, но как насчет семантики перемещения? мне тоже нужно это реализовать   -  person tjwrona1992    schedule 01.08.2018
comment
@SamVarshavchik, можно поподробнее? Я не совсем понимаю, что вы имеете в виду. Код, который это делает, должен использоваться в качестве замены для другого класса интеллектуальных указателей, поэтому необходимо неявное преобразование типов, иначе это потребует изменений кода во всей нашей системе, чтобы заставить ее работать с новым типом.   -  person tjwrona1992    schedule 01.08.2018
comment
@tjwrona1992 См. это для всего, что поддерживается.   -  person NathanOliver    schedule 01.08.2018
comment
@SamVarshavchik Где ОП возвращает ссылку?   -  person NathanOliver    schedule 01.08.2018
comment
В операторе преобразования.   -  person Sam Varshavchik    schedule 01.08.2018
comment
@SamVarshavchik Тип возвращаемого значения — std::shared_ptr<U>. const & - это const и ссылочные характеристики функции.   -  person NathanOliver    schedule 01.08.2018
comment
Правая часть () не является частью возвращаемого типа.   -  person NathanOliver    schedule 01.08.2018
comment
@NathanOliver, означает ли это, что в Visual Studio 2013 невозможно реализовать семантику перемещения? то есть operator typename std::shared_ptr<U>() const && { ... }   -  person tjwrona1992    schedule 01.08.2018
comment
@ tjwrona1992 Это не то, что реализует семантику перемещения. наличие & в конце функции означает, что только lvalue может вызывать эту функцию. Наличие && означает, что только rvalue может вызывать эту функцию. MSVS 2013 поддерживает ссылки на rvalue и семантику перемещения. operator typename std::shared_ptr<U>() const сделает то, что вы хотите.   -  person NathanOliver    schedule 01.08.2018
comment
@NathanOliver, хорошо, спасибо. Последний вопрос. Извините, что так много спрашиваю. Если удаление & сделает все, что я хочу, то какова цель определения операторов преобразования с помощью & или && при отключении & делает все?   -  person tjwrona1992    schedule 01.08.2018
comment
@ tjwrona1992 Целью может быть то, что вы хотите, чтобы можно было конвертировать только lvalue или rvalue. Не знаю, зачем вам это, но вы можете это получить.   -  person NathanOliver    schedule 01.08.2018
comment
@NathanOliver, как насчет ситуации, когда вы хотите это сделать? std::shared_ptr<int> ptr = std::move(myobject); Перемещение не приведет к отказу от владения объектом, если вы не реализовали другое преобразование для объектов rvalue, которое явно отказывается от владения.   -  person tjwrona1992    schedule 01.08.2018