首页 > 解决方案 > 这是 GCC 中可能存在的错误吗?

问题描述

我的团队有一个内部概念的实现,我们遇到了似乎是 GCC 的错误。以下代码将在 Visual Studio 2019 上运行,但在 GCC 8.3 上失败:

#include <type_traits>
#include <iterator>

template <typename T>
constexpr auto name(int, T &instance = std::declval<T &>()) -> decltype(
    std::declval<decltype(std::begin(instance)) &>(), std::true_type{}) { return {}; }

template <typename>
constexpr auto name(...) -> decltype(std::true_type{}) { return {}; }

auto main() -> int {
    auto&& t =std::declval<nullptr_t>();
    name<nullptr_t>(0);
}

Godbolt 上的 GCC 8.3 和我们的 WSL 安装返回以下错误:

In file included from <source>:1:

/opt/compiler-explorer/gcc-8.3.0/include/c++/8.3.0/type_traits: In instantiation of 'decltype (__declval<_Tp>(0)) std::declval() [with _Tp = std::nullptr_t; decltype (__declval<_Tp>(0)) = std::nullptr_t&&]':

<source>:12:39:   required from here

/opt/compiler-explorer/gcc-8.3.0/include/c++/8.3.0/type_traits:2058:21: error: static assertion failed: declval() must not be used!

       static_assert(__declval_protector<_Tp>::__stop,

                     ^~~~~~~~~~~~~~~~~~~~~~~~

Compiler returned: 1

关于这可能是什么的任何帮助?

标签: c++gccgcc8

解决方案


实际上 gcc 是这里的理智编译器,考虑到你在做什么:

T &instance = std::declval<T &>()

在争论中。正如cppreference所说:

注意 declval 只能用在未计算的上下文中,不需要定义;评估包含此函数的表达式是错误的。形式上,如果这个函数被 odr-used,那么程序是非良构的。

因此,与 GCC 中的错误相比,MSVC 的检查相当糟糕。declval如您所见,完全允许不定义。


推荐阅读