3

My team has an in-house implementation of concepts and we've come across what seems to be a bug with GCC. The following code will work on Visual Studio 2019 but fail on 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);
}

GCC 8.3 on Godbolt and our WSL installations returns the following error:

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

Any help on what this could be?

ruipacheco
  • 15,025
  • 19
  • 82
  • 138

1 Answers1

2

Actually gcc is the sane compiler here considering what you are doing:

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

in arguments. As cppreference says:

Note that declval can only be used in unevaluated contexts and is not required to be defined; it is an error to evaluate an expression that contains this function. Formally, the program is ill-formed if this function is odr-used.

So it is rather poor checks from MSVC than bug in GCC. declval as you see is perfectly allowed not to be defined.

bartop
  • 9,971
  • 1
  • 23
  • 54