Это возможная ошибка в GCC? - PullRequest
3 голосов
/ 11 октября 2019

У моей команды есть собственная реализация концепций, и мы столкнулись с тем, что кажется ошибкой в ​​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);
}

GCC 8.3 на Godbolt, и наши установки 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

Любая помощь в том, чтоэто может быть?

1 Ответ

2 голосов
/ 11 октября 2019

На самом деле gcc - это нормальный компилятор, который учитывает, что вы делаете:

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

в аргументах. Как cppreference говорит:

Обратите внимание, что declval может использоваться только в неоцененных контекстах и ​​не требует определения;Ошибка в оценке выражения, содержащего эту функцию. Формально программа плохо сформирована, если эта функция используется odr.

Таким образом, проверки в MSVC скорее плохие, чем ошибки в GCC. declval как видите, совершенно не разрешено определять.

...