шаблонная строка оператора() не будет компилироваться, когда временный объект

Кто-нибудь знает, почему последняя строка в main не компилируется (обратите внимание, что компиляция не выполняется):

template <typename TT> inline TT getAs();
template <>            string getAs() { return "bye"; }
template <>            int getAs() { return 123; }

class Foo
{
public:
    template <typename TT>
        inline operator TT() const { return ::getAs<TT>(); }
    template <typename TT>
        inline string getAs() const { return ::getAs<TT>(); }
};

Foo tempFoo() { return Foo(); }

int main()
{
    Foo foo;
    string testStringLocal = foo;       // OK
    int testIntTemp = tempFoo();        // OK
    string testStringTemp = tempFoo().getAs<string>();  // OK
    const string& testStringTemp2 = tempFoo();  // OK

    string testStringTemp3 = tempFoo(); //.getAs<string>();  // FAIL!
}

Как я указал в комментариях к основным строкам,

  • неявное преобразование из Foo в строку отлично компилируется для невременного объекта (например, foo),
  • а также на временном объекте при преобразовании в int (или long и т. д.)
  • он отлично работает при преобразовании в строку с помощью метода
  • а также если тип const string& вместо строки

Пробовал это на VS2010. Обратите внимание, что приведенный выше код отлично компилируется в 2005 году, но я считаю, что 2010 год подходит.

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

class Foo
{
public:
    operator string() const { return ::getAs<string>(); }
    operator int()    const { return ::getAs<int>(); }
    ...
};

Я бы предпочел не использовать этот обходной путь, поскольку он менее ремонтопригоден.

Кто-нибудь знает другой способ успешной компиляции последней строки main()? Я не думаю, что принятый ответ на оператор явного преобразования и шаблонного преобразования применим здесь, потому что возможны множественные преобразования (char *, alloc, string) независимо от того, задействованы ли шаблоны, и тот факт, что объект является временным, кажется, имеет значение.

РЕДАКТИРОВАТЬ: Исходный код в этом посте показал некоторую специализацию шаблонов в классе, это был артефакт создания автономного фрагмента кода для SO из моего исходного источника (я переместил некоторые специализации на уровне пространства имен в класс, и VS2010 не жаловался ). Проблема не в специализации. Я изменил размещенный код, чтобы он был ближе к оригиналу (как я только что сделал), не использует специализацию в классе (конечно, проблема все еще существует). Ответ Дерека указывает, что это может быть связано с VS2010.


person Oliver    schedule 03.01.2014    source источник


Ответы (1)


Не знаю о Visual C++ 2010 (я думаю, версия 9.0), но вы не можете специализировать шаблонную функцию-член в самом классе. Это должно быть сделано в области пространства имен, в соответствии с ошибками, выдаваемыми более современными компиляторами, которым я дал этот код.

So,

#include <string>
using namespace std;

class Foo
{
public:
    template <typename TT> inline operator TT()     const;
    template <typename TT> inline TT       getAs()  const;
};

template <>  inline Foo::operator string() const { return "hi"; }
template <>  inline Foo::operator int()    const { return 123; }
template <>  inline string Foo::getAs()  const { return "bye"; }

Foo tempFoo() { return Foo(); }

int main()
{
    Foo foo;
    string testStringLocal = foo;       // OK
    int testIntTemp = tempFoo();        // OK
    string testStringTemp = tempFoo().getAs<string>();  // OK

    string testStringTemp2 = tempFoo();  // OK!
}

Отлично компилируется с Visual C++ 12.0 и g++ 4.7.2.

person Cheers and hth. - Alf    schedule 03.01.2014
comment
Спасибо, но это определенно не из-за специализации: исходный код моего приложения не включает специализации в классе, я вставил их при создании автономного примера (не знаю, почему VS 2010 не жаловался). Я отредактировал соответственно. Но код, который вы показываете, указывает, что, возможно, это проблема 2010 года, я посмотрю, смогу ли я воспроизвести его в VS2012 Express с моим отредактированным кодом. - person Oliver; 03.01.2014
comment
Не работает и в 2012 году, поэтому, к сожалению, этот ответ также косвенно не решает проблему (согласно отредактированному сообщению). Я создал новый вопрос. - person Oliver; 04.01.2014