在 if constexpr 中使用带有参数包的概念时升级到 gcc 9 后出现编译错误
Compilation error after upgrade to gcc 9 when using concepts with argument pack in if constexpr
我有一段代码在 if constexpr
上下文中使用带有参数包的概念。它曾经在 gcc 8 中编译和工作,但在 gcc 9 中中断:
#include <utility>
#include <tuple>
template <typename T, typename ...Ts>
concept
#if __GNUC__ < 9
bool
#endif
is_handled = requires(T handler, Ts && ...args) {
handler.handle(std::forward<Ts>(args)...);
};
template <typename T>
concept
#if __GNUC__ < 9
bool
#endif
has_name = requires(T) {
T::name;
};
template <typename ...Handlers>
struct Dispatcher {
template <typename ...Ts>
void operator()(Ts && ...args) {
std::apply(
[&](auto && ...handlers) {
(handle(handlers, std::forward<Ts>(args)...),...);
},
m_handlers
);
}
private:
template <typename Handler, typename ...Ts>
void handle(Handler & handler, Ts && ...args) {
if constexpr (is_handled<Handler, Ts...>) {
handler.handle(std::forward<Ts>(args)...);
}
}
template <typename Handler>
char const* get_code() {
if constexpr (has_name<Handler>) {
return Handler::name;
}
return nullptr;
}
std::tuple<Handlers...> m_handlers;
};
GCC 9.2 产生的错误是:
<source>: In member function 'void Dispatcher<Handlers>::handle(Handler&, Ts&& ...)':
<source>:38:49: error: expected unqualified-id before ')' token
38 | if constexpr (is_handled<Handler, Ts...>) {
| ^
See compiler explorer here。您可以在 gcc 8.3 和 9.2 版本之间切换以查看差异。
你是正确的,它应该编译并且它是 GCC 9.1 中的回归。
GCC 的错误跟踪器中已经有关于此的错误报告 here。
您可以通过在 if constexpr
条件周围放置额外的括号来避免解析器错误,强制将其解析为表达式而不是声明:
if constexpr ((is_handled<Handler, Ts...>)) {
//...
}
我有一段代码在 if constexpr
上下文中使用带有参数包的概念。它曾经在 gcc 8 中编译和工作,但在 gcc 9 中中断:
#include <utility>
#include <tuple>
template <typename T, typename ...Ts>
concept
#if __GNUC__ < 9
bool
#endif
is_handled = requires(T handler, Ts && ...args) {
handler.handle(std::forward<Ts>(args)...);
};
template <typename T>
concept
#if __GNUC__ < 9
bool
#endif
has_name = requires(T) {
T::name;
};
template <typename ...Handlers>
struct Dispatcher {
template <typename ...Ts>
void operator()(Ts && ...args) {
std::apply(
[&](auto && ...handlers) {
(handle(handlers, std::forward<Ts>(args)...),...);
},
m_handlers
);
}
private:
template <typename Handler, typename ...Ts>
void handle(Handler & handler, Ts && ...args) {
if constexpr (is_handled<Handler, Ts...>) {
handler.handle(std::forward<Ts>(args)...);
}
}
template <typename Handler>
char const* get_code() {
if constexpr (has_name<Handler>) {
return Handler::name;
}
return nullptr;
}
std::tuple<Handlers...> m_handlers;
};
GCC 9.2 产生的错误是:
<source>: In member function 'void Dispatcher<Handlers>::handle(Handler&, Ts&& ...)':
<source>:38:49: error: expected unqualified-id before ')' token
38 | if constexpr (is_handled<Handler, Ts...>) {
| ^
See compiler explorer here。您可以在 gcc 8.3 和 9.2 版本之间切换以查看差异。
你是正确的,它应该编译并且它是 GCC 9.1 中的回归。
GCC 的错误跟踪器中已经有关于此的错误报告 here。
您可以通过在 if constexpr
条件周围放置额外的括号来避免解析器错误,强制将其解析为表达式而不是声明:
if constexpr ((is_handled<Handler, Ts...>)) {
//...
}