Clang"异常规范的解决方法在类定义结束之前不可用"错误

时间:2018-01-19 11:47:26

标签: c++ c++11 clang compiler-bug

鉴于此代码:

template <typename>
struct Check { constexpr static bool value = true; };

struct A {
    A() noexcept(Check<int>::value) = default;
};

使用各种版本的GNU g++进行编译工作正常,但它总是失败,clang++ 5.0.1(使用libstdc ++和libc ++):

$ g++-4.9.4 test.cpp -c -o test -std=c++11 -Wall -Wextra
$ g++-5.4.0 test.cpp -c -o test -std=c++11 -Wall -Wextra
$ g++-6.4.0 test.cpp -c -o test -std=c++11 -Wall -Wextra
$ g++-7.2.0 test.cpp -c -o test -std=c++11 -Wall -Wextra
$ clang++ test.cpp -c -o test -std=c++11 -Wall -Wextra -Weverything
test.cpp:2:16: warning: 'constexpr' specifier is incompatible with C++98 [-Wc++98-compat]
struct Check { constexpr static bool value = true; };
            ^
test.cpp:5:39: warning: defaulted function definitions are incompatible with C++98 [-Wc++98-compat]
    A() noexcept(Check<int>::value) = default;
                                    ^
test.cpp:5:9: warning: noexcept specifications are incompatible with C++98 [-Wc++98-compat]
    A() noexcept(Check<int>::value) = default;
        ^
test.cpp:5:5: error: exception specification is not available until end of class definition
    A() noexcept(Check<int>::value) = default;
    ^
test.cpp:5:18: note: in instantiation of template class 'Check<int>' requested here
    A() noexcept(Check<int>::value) = default;
                ^
3 warnings and 1 error generated.
$ clang++ test.cpp -c -o test -std=c++11 -Wall -Wextra
test.cpp:5:5: error: exception specification is not available until end of class definition
    A() noexcept(Check<int>::value) = default;
    ^
test.cpp:5:18: note: in instantiation of template class 'Check<int>' requested here
    A() noexcept(Check<int>::value) = default;
                ^
1 error generated.

Compiler Explorer上这似乎也适用于所有版本的GCC较新的4.7.0(包括主干),但除了Clang 3.4.0,3.5.0,3.5.1和trunk之外的所有Clang版本都失败了。所以这看起来像是Clang bug。

是否可以解决此错误?怎么样?这个bug已经在某个地方被跟踪了吗?

编辑:

我将此错误追踪到Clang PR23383。到目前为止,没有任何关于在Clang中修复此问题的通知,尽管它似乎与Compiler Explorer中的Clang主干一起使用。

这可能与PR30860(以及C++ DR1330中所述的Richard Smith's comment on PR30860)有关。似乎该问题与解析noexcept()的内容时有关。

事实证明,一个明显的解决方法是尝试强制编译器在其他地方解析这些内容。一种可能的解决方案是将内容noexcept()作为constexpr成员常量提供:

template <typename>
struct Check { constexpr static bool value = true; };

struct A {

    A() noexcept(workaround) = default;

private: /* Work around Clang PR23383: */

    static constexpr bool workaround = Check<int>::value;

};

不幸的是,这并不适用于所有情况,例如:比如:

#include <type_traits>

struct Base { virtual ~Base() noexcept; };

struct OuterClass {

    class InnerDerived: public Base {
    private:
        static constexpr auto const workaround =
                std::is_nothrow_default_constructible<Base>::value;
    public:
        InnerDerived() noexcept(workaround);
    };

    class InnerDerived2: public InnerDerived {
    private:
        static constexpr auto const workaround2 =
                std::is_nothrow_default_constructible<InnerDerived>::value;
    public:
        InnerDerived2() noexcept(workaround2);
    };

};

即使在Compiler Explorer中使用Clang trunk,后者也会产生错误。 有什么想法?

0 个答案:

没有答案