【问题标题】:How to workaround gcc-3.4 bug (or maybe this is not a bug)?如何解决 gcc-3.4 错误(或者这可能不是错误)?
【发布时间】:2010-03-02 06:59:05
【问题描述】:

以下代码失败并显示错误消息:

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 类的级别上解决它,或者我的代码可能是错误的,如果是这样,在哪里?

编辑:

Bugs related to template-functions in GCC 3.4.6 说我需要使用关键字template 但我应该使用吗?

这是一个错误吗?我必须写一个template 关键字吗?因为在所有其他情况下我都不必?而且很连线我用“.c_str()”成员函数的时候不用写。

为什么 gcc-4 并不总是一种选择

这个程序在Cygwin下用gcc-4编译时不启动

#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;
}

并且此代码在 OpenSolaris 2009 下无法使用 gcc-4.3 编译 - 损坏的概念检查...

#include <map>
struct tree {
   std::map<int,tree> left,right;
};

【问题讨论】:

  • 如果您的编译器在这种情况下需要关键字template,那么这是编译器中的一个错误translate 函数的返回类型不依赖于任何模板参数。此处不需要关键字template。您的代码在其原始形式中很好。
  • template 这里是必需的,因为str 是一个模板方法。
  • 那么任何人都可以判断这是否是功能错误?
  • 从长远来看,升级 GCC 不是更好吗?您还将获得更好的优化代码。
  • gcc-3.4 在某些平台上只能选择的问题:Cygwin、OpenSolaris。

标签: c++ gcc


【解决方案1】:

正如在其他地方提到的,这似乎是一个编译器错误。很公平;那些存在。以下是您对这些内容的处理方式:

#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__ 定义为主要编译器版本号。如果需要,您还可以获取 x.y.z 版本号的 y 和 z 的 __GNUC_MINOR____GNUC_PATCHLEVEL__

【讨论】:

    【解决方案2】:

    这是旧编译器中的一个错误。较新的 GCC,从 4.0 到(尚未发布的)4.5,应该接受它。它是标准的 C++。 (英特尔和 Comeau 也接受它。)

    关于 cygwin 和 opensolaris,当然 gcc-3.4 不是唯一的选择:较新的版本(已发布的 4.4.3 或未发布的 4.5 分支)在这些操作系统上运行良好。对于 cygwin,它是官方发行版的一部分(参见 gcc4*in the list)。对于 opensolaris,您可以自己编译(通过 Google 可以轻松找到有关如何编译的说明)。

    【讨论】:

    • 是的——不过,对于分发给其他用户的程序,“您需要编译一个编译器才能构建它”并没有多大吸引力......
    • 查看我的 gcc-4.3 损坏示例。 gcc-4.x 并不总是一种选择。
    【解决方案3】:

    我会尝试使用不同的解决方法,因为添加 template 消歧器是不正确的,并且如果您稍后移至不同的编译器会中断。

    我不知道真正的代码,但是传递一个常规的 std::string 似乎可以工作(选项 1:避免转换为 const char * 只是为了创建一个临时代码)或者您可以提供一个重载的 translate,它需要一个const char* 作为参数(如果编译器没有在那里抱怨),这取决于您的要求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-14
      • 2013-07-12
      • 2011-09-16
      相关资源
      最近更新 更多