我遇到了一个相当麻烦的情况,我试图将 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>
标头内)不完整,但它应该有一个布尔值的 constexprvalue
成员。这就是我认为的错误,因为 g++8 可以很好地编译它。据推测,该错误存在于 libstdc++ 的 std::any 和/或 std::is_copy_constructible 实现中,但由于 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::any 的构造函数,模板参数推导的所有候选者都失败,包括应该工作但埋在该构造函数中的构造函数是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++ 中的一个错误,对吧?