Mon équipe a une implémentation interne des concepts et nous avons rencontré ce qui semble être un bogue avec GCC. Le code suivant fonctionnera sur Visual Studio 2019 mais échouera sur 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 sur Godbolt et nos installations WSL renvoie l'erreur suivante :

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

Une aide sur ce que cela pourrait être?

3
ruipacheco 11 oct. 2019 à 12:31

1 réponse

Meilleure réponse

En fait, gcc est le compilateur sensé ici compte tenu de ce que vous faites :

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

En argumentation. Comme le dit cppreference :

Notez que declval ne peut être utilisé que dans des contextes non évalués et n'a pas besoin d'être défini ; c'est une erreur d'évaluer une expression qui contient cette fonction. Formellement, le programme est mal formé si cette fonction est utilisée par odr.

Il s'agit donc plutôt de mauvaises vérifications de MSVC que de bogues dans GCC. declval comme vous le voyez est parfaitement autorisé à ne pas être défini.

2
bartop 11 oct. 2019 à 09:53