Следующий код выдает сообщение об ошибке:

t.cpp: In function `void test()':
t.cpp:35: error: expected primary-expression before '>' token
t.cpp:35: error: expected primary-expression before ')' token

Сейчас я не вижу проблем с кодом, и он компилируется с gcc-4.x и MSVC 2005, но не с gcc-3.4 (который все еще довольно популярен на некоторых платформах).

#include <string>
#include <iostream>

struct message {
        message(std::string s) : s_(s) {}
        template<typename CharType>
        std::basic_string<CharType> str()
        {
                return std::basic_string<CharType>(s_.begin(),s_.end());
        }
private:
        std::string s_;
};


inline message translate(std::string const &s)
{
        return message(s);
}


template<typename TheChar>
void test()
{
        std::string s="text";
        std::basic_string<TheChar> t1,t2,t3,t4,t5;

        t1=translate(s).str<TheChar>(); // ok

        char const *tmp=s.c_str();
        t2=translate(tmp).str<TheChar>(); // ok

        t3=message(s.c_str()).str<TheChar>(); // ok

        t4=translate(s.c_str()).str<TheChar>(); // fails

        t5=translate(s.c_str()).template str<TheChar>(); // ok

        std::cout << t1 <<" " << t2 <<" " << t3 << " " << t4 << std::endl;
}

int main()
{
        test<char>();
}

Можно ли обойти это на уровне функции translate и класса message, или, может быть, мой код неправильный, если да, то где?

Изменить:

Ошибки, связанные с функциями шаблонов в GCC 3.4.6 < / a> говорит, что мне нужно использовать ключевое слово template, но следует ли?

Это ошибка? Нужно ли мне писать ключевое слово template? Потому что во всех остальных случаях мне это не нужно? И это довольно зашито, мне не нужно писать его, когда я использую функцию-член ".c_str ()".

Почему gcc-4 не всегда подходит

Эта программа не запускается при компиляции с gcc-4 под Cygwin

#include <iostream>
#include <locale>

class bar : public std::locale::facet  {
public:
        bar(size_t refs=0) : std::locale::facet(refs)
        {
        }
        static std::locale::id id;
};

std::locale::id bar::id;


using namespace std;

int main()
{
        std::locale l=std::locale(std::locale(),new bar());
        std::cout << has_facet<bar>(l) << std::endl;
        return 0;
}

И этот код не компилируется с gcc-4.3 под OpenSolaris 2009 - проверка нарушенных концепций ...

#include <map>
struct tree {
   std::map<int,tree> left,right;
};
2
Artyom 2 Мар 2010 в 09:59
Если вашему компилятору требуется ключевое слово template в этом случае, то это ошибка в компиляторе. Тип возвращаемого значения функции translate не зависит от каких-либо параметров шаблона. Ключевое слово template здесь не требуется. Ваш код прекрасен в исходном виде.
 – 
AnT
2 Мар 2010 в 10:37
Так может ли кто-нибудь сказать, является ли это ошибкой функции?
 – 
Artyom
2 Мар 2010 в 10:56
Не лучше ли в долгосрочной перспективе просто обновить GCC? Вы также получите лучше оптимизированный код.
 – 
LiraNuna
2 Мар 2010 в 11:01
Проблема в том, что gcc-3.4 доступен только на некоторых платформах: Cygwin, OpenSolaris.
 – 
Artyom
2 Мар 2010 в 11:05

3 ответа

Лучший ответ

Как упоминалось в другом месте, похоже, что это ошибка компилятора. Справедливо; те существуют. Вот что с этим делать:

#if defined(__GNUC__) && __GNUC__ < 4
// Use erroneous syntax hack to work around a compiler bug.
t4=translate(s.c_str()).template str<TheChar>();
#else
t4=translate(s.c_str()).str<TheChar>();
#endif

GCC всегда определяет __GNUC__ как основной номер версии компилятора. Если вам это нужно, вы также получите __GNUC_MINOR__ и __GNUC_PATCHLEVEL__ для y и z номера версии x.y.z.

2
Brooks Moses 2 Мар 2010 в 13:37

Это ошибка старого компилятора. Новые GCC, от 4.0 до (еще не выпущенной) 4.5, принимают его, как должны. Это стандартный C ++. (Intel и Комо также принимают это.)

Что касается cygwin и opensolaris, конечно, gcc-3.4 - не единственный вариант: более новые версии (выпущенная 4.4.3 или невыпущенная ветка 4.5) отлично работают с этими ОС. Для cygwin это часть официального дистрибутива (см. gcc4* пакеты в списке). Для opensolaris вы можете скомпилировать его самостоятельно (и инструкции о том, как это сделать, можно легко найти в Google).

2
F'x 2 Мар 2010 в 11:24
Верно - хотя для программы, распространяемой среди других пользователей, «вам нужно будет скомпилировать компилятор, чтобы ее построить» не так уж и привлекает ...
 – 
Brooks Moses
2 Мар 2010 в 12:51
Смотрите мои примеры, когда gcc-4.3 не работает. gcc-4.x - не всегда вариант.
 – 
Artyom
2 Мар 2010 в 13:26

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

Я не знаю настоящего кода, но передача обычного std::string, похоже, работает (вариант 1: избегайте преобразования в const char * только для создания временного кода), или вы можете предоставить перегруженный translate который принимает в качестве аргумента const char* (если компилятор там не жалуется), в зависимости от ваших требований.

1
David Rodríguez - dribeas 2 Мар 2010 в 11:29