Это ошибка в libstdc ++ с std :: any или std :: is_copy_constructible, или это ошибка le git? - PullRequest
0 голосов
/ 26 марта 2020

Я столкнулся с довольно тревожной ситуацией, в которой я пытаюсь использовать std :: make_any с классом, который я написал, который принимает std :: any в одном из своих конструкторов, но при попытке придумать минимальный тестовый случай, я столкнулся с тем, что я думаю, вероятно, является ошибкой в ​​реализации std :: any и / или std :: is_copy_constructible, однако я не уверен на 100%. Вот несколько минимальных примеров, которые по-разному работают или не работают с использованием g ++ 8 и clang ++ 9. В каждом примере присутствуют все одинаковые строки кода, но в 4 состояниях две строки закомментированы или нет, и результат.

Я использую стандарт C ++ 17, передавая -std=c++17 помечают как g ++ - 8, так и clang ++ - 9, и они оба используют libstdc ++ версии 8.3.0 (Ubuntu 18.04).

Следующие компиляции используют как g ++ - 8, так и clang ++ - 9.

#include <any>
#include <type_traits>

struct Hippo {
    Hippo () { }
    Hippo (Hippo const &) { }
    Hippo (Hippo &&) { }
//     Hippo (std::any) { }
};

int main (int argc, char **argv) {
    static_assert(std::is_copy_constructible_v<Hippo>);
//     auto w = std::make_any<Hippo>();
    return 0;
}

Следующее также работает для обоих, как и следовало ожидать.

#include <any>
#include <type_traits>

struct Hippo {
    Hippo () { }
    Hippo (Hippo const &) { }
    Hippo (Hippo &&) { }
//     Hippo (std::any) { }
};

int main (int argc, char **argv) {
    static_assert(std::is_copy_constructible_v<Hippo>);
    auto w = std::make_any<Hippo>();
    return 0;
}

Следующее компилируется с g ++ - 8, но завершается неудачно с clang ++ - 9. Это сбивает с толку, потому что значение std::is_copy_constructible_v<Hippo> не должно изменяться путем добавления конструктора, не связанного с конструкцией копирования.

#include <any>
#include <type_traits>

struct Hippo {
    Hippo () { }
    Hippo (Hippo const &) { }
    Hippo (Hippo &&) { }
    Hippo (std::any) { }
};

int main (int argc, char **argv) {
    static_assert(std::is_copy_constructible_v<Hippo>);
//     auto w = std::make_any<Hippo>();
    return 0;
}

Ошибка, выдаваемая clang ++ - 9: (обрезается по длине):

/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/type_traits:132:31: error: no member named 'value' in 'std::is_copy_constructible<Hippo>'
    : public conditional<_B1::value, _B2, _B1>::type
                         ~~~~~^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/any:170:17: note: in instantiation of template class 'std::__and_<std::is_copy_constructible<Hippo>, std::is_constructible<Hippo, const Hippo &> >' requested here
      enable_if<__and_<is_copy_constructible<_Tp>,

Здесь, похоже, что тип std::is_copy_constructible<Hippo> является неполным в момент использования (в заголовке <any>), но он должен иметь bool-valueed элемент constexpr value. Это то, что я считаю ошибкой, поскольку g ++ 8 компилирует это просто отлично. Предположительно, ошибка заключается в реализации stst :: any и / или std :: is_copy_constructible в libstdc ++, но поскольку g ++ - 8 работает, а clang ++ - 9 не работает, это сбивает с толку.

Тем не менее, следующее не компилируется в и g ++ - 8, и clang ++ - 9:

#include <any>
#include <type_traits>

struct Hippo {
    Hippo () { }
    Hippo (Hippo const &) { }
    Hippo (Hippo &&) { }
    Hippo (std::any) { }
};

int main (int argc, char **argv) {
    static_assert(std::is_copy_constructible_v<Hippo>);
    auto w = std::make_any<Hippo>();
    return 0;
}

Неудивительно, что ошибка, вызванная clang ++ - 9, одинакова, но ошибка из g ++ - 8 утверждает, что все кандидаты на вывод аргумента шаблона терпят неудачу для std: Любой конструктор, в том числе тот, который должен работать, но скрытый в этом конструкторе, использует std :: is_copy_constructible, поэтому я думаю, что это та же самая проблема, и я уверен, что это ошибка. Я вырезал нерелевантные части сообщения об ошибке:

/usr/include/c++/8/any: In instantiation of ‘std::any std::make_any(_Args&& ...) [with _Tp = Hippo; _Args = {}]’:
.../any.cpp:13:35:   required from here
/usr/include/c++/8/any:431:14: error: no matching function for call to ‘std::any::any(const std::in_place_type_t<Hippo>&)’
       return any(in_place_type<_Tp>, std::forward<_Args>(__args)...);
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<...cut for length...>
/usr/include/c++/8/any:208:7: note: candidate: ‘template<class _ValueType, class ... _Args, class _Tp, class _Mgr, typename std::enable_if<std::__and_<std::is_copy_constructible<_Tp>, std::is_constructible<_Tp, _Args&& ...> >::value, bool>::type <anonymous> > std::any::any(std::in_place_type_t<_Tp>, _Args&& ...)’
       any(in_place_type_t<_ValueType>, _Args&&... __args)
       ^~~
/usr/include/c++/8/any:208:7: note:   template argument deduction/substitution failed:
<...cut for length...>

В любом случае, мой вопрос стоит - это ошибка в libstdc ++, верно?

1 Ответ

0 голосов
/ 26 марта 2020

Полностью исследуя этот вопрос, я попытался скомпилировать против libc ++ (используя только clang ++ - 9) вместо libstdc ++, и это решило проблему. Таким образом, может показаться, что это ошибка le git в libstdc ++ 8.3.0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...