【问题标题】:Is this a bug of gcc?这是gcc的错误吗?
【发布时间】:2017-06-04 07:34:19
【问题描述】:
#include <codecvt>
#include <string>
#include <locale>

std::string to_gbk(const std::wstring& u16_str)
{
        using Facet = std::codecvt_byname<wchar_t, char, std::mbstate_t>;
        std::wstring_convert
                <std::codecvt<wchar_t, char, std::mbstate_t>>
                wstr_2_gbk(new Facet("zh_CN.GBK"));

        return wstr_2_gbk.to_bytes(u16_str);
}

int main()
{
        to_gbk(L"");
}

clang 和 vc++ 都可以,但是 gcc 6.2 输出:

[root@localhost ~]# g++ main.cpp 
In file included from /usr/include/c++/6.2.1/bits/locale_conv.h:41:0,
                 from /usr/include/c++/6.2.1/locale:43,
                 from main.cpp:3: /usr/include/c++/6.2.1/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = std::codecvt<wchar_t, char, __mbstate_t>]’:
/usr/include/c++/6.2.1/bits/unique_ptr.h:236:17:   required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = std::codecvt<wchar_t, char, __mbstate_t>; _Dp = std::default_delete<std::codecvt<wchar_t, char, __mbstate_t> >]’
/usr/include/c++/6.2.1/bits/locale_conv.h:218:7:   required from here
/usr/include/c++/6.2.1/bits/unique_ptr.h:76:2: error: ‘virtual std::codecvt<wchar_t, char, __mbstate_t>::~codecvt()’ is protected within this context
delete __ptr;
^~~~~~
In file included from /usr/include/c++/6.2.1/codecvt:41:0,
                 from main.cpp:1:
/usr/include/c++/6.2.1/bits/codecvt.h:426:7: note: declared protected here
       ~codecvt();
       ^

这是 gcc 的错误吗?

【问题讨论】:

  • 程序员经常怀疑 CPU 中的错误,然后在编译器中,最迟他们发现自己的错误:)
  • @latedeveloper 这是一个答案!
  • @i486 - 这不是这里的情况。实现在这里是不确定的。

标签: c++ gcc compiler-bug


【解决方案1】:

这是gcc的bug吗?

没有。 std::codecvt 的析构函数受到保护。参见 [locale.codecvt](标准草案):

template <class internT, class externT, class stateT>
class codecvt : public locale::facet, public codecvt_base {
// ...
protected:
    ~codecvt();
};

显然,其他实现已选择提高公众的可见性,但这不是标准所要求的。


另见LWG issue 721(判定为不是缺陷)。

这是刻面原始设计的一个令人遗憾的结果。

缺陷报告中还有一个如何构造此类对象的示例:

template<class I, class E, class S>
struct codecvt : std::codecvt<I, E, S>
{
    ~codecvt()
    { }
}

...

std::wstring_convert<codecvt<wchar_t, char, std::mbstate_t> >;

【讨论】:

  • 我很惊讶地看到 void main() 和 Bo of all people 的 LWG 问题
  • 如果它受到保护,是否意味着您可以通过从codecvt 派生新类来绕过错误?
  • @MarkRansom:这意味着你必须
  • @MarkRansom 派生,如引用的示例所示,确实允许增加析构函数的可见性,并且使用这样的方面应该是格式正确的。 (“codecvt&lt;wchar_t,char,mbstate_t&gt; 在窄字符和宽字符的本地字符集之间转换”。)
  • 对不起,我错过了这个例子——它是在我决定发表评论后编辑的。
猜你喜欢
  • 2013-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
  • 1970-01-01
  • 2012-04-10
相关资源
最近更新 更多