Я столкнулся с довольно тревожной ситуацией, в которой я пытаюсь использовать 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 ++, верно?