鉴于此代码:
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,后者也会产生错误。 有什么想法?