尝试在具有 std::any 构造函数的基类中调用复制构造函数时出现问题

mar*_*f78 6 c++ clang++ c++17

考虑以下代码:

#include <any>

struct A {
    A();
    A(const A&) = default;
    explicit A(std::any value);
};

struct B: A {
    B() : A() { }
    B(const B& b) : A(b) {}
    explicit B(std::any value) : A(value) {}
};
Run Code Online (Sandbox Code Playgroud)

编译器在编译时报告以下错误(使用 clang++-5 或更高版本):

In file included from <source>:2:
In file included from /opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/any:37:
In file included from /opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/new:40:
In file included from /opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/exception:143:
In file included from /opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/bits/nested_exception.h:40:
In file included from /opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/bits/move.h:54:
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/type_traits:149:31: error: no member named 'value' in 'std::is_copy_constructible<B>'
: public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type
                     ~~~~~^
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/any:192:27: note: in instantiation of template class 'std::__and_<std::is_copy_constructible<B>, std::__not_<std::is_constructible<B, const B &> >, std::__not_<std::__is_in_place_type<B> > >' requested here
          enable_if_t<__and_<is_copy_constructible<_Tp>,
                      ^
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/any:196:7: note: while substituting prior template arguments into non-type template parameter [with _ValueType = const B &, _Tp = B, _Mgr = std::any::_Manager_external<B>]
  any(_ValueType&& __value)
  ^~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/type_traits:973:28: note: while substituting deduced template arguments into function template 'any' [with _ValueType = const B &, _Tp = (no value), _Mgr = (no value), $3 = (no value)]
         = decltype(::new _Tp(declval<_Arg>()))>
                              ^
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/type_traits:974:24: note: in instantiation of default argument for '__test<B, const B &>' required here
  static true_type __test(int);
                   ^~~~~~~~~~~
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/type_traits:984:24: note: while substituting deduced template arguments into function template '__test' [with _Tp = B, _Arg = const B &, $2 = (no value)]
  typedef decltype(__test<_Tp, _Arg>(0)) type;
                   ^
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/type_traits:144:14: note: (skipping 9 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
: public conditional<_B1::value, _B2, _B1>::type
         ^
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/any:170:17: note: in instantiation of template class 'std::__and_<std::is_copy_constructible<B>, std::is_constructible<B, const B &> >' requested here
  enable_if<__and_<is_copy_constructible<_Tp>,
            ^
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/any:175:5: note: in instantiation of template type alias '__any_constructible' requested here
using __any_constructible_t =
^
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/any:181:56: note: in instantiation of template type alias '__any_constructible_t' requested here
          __any_constructible_t<_Tp, _ValueType&&> = true,
                                                   ^
/opt/compiler-explorer/gcc-7.3.0/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/any:183:7: note: while substituting prior template arguments into non-type template parameter [with _ValueType = const B &, _Tp = B, _Mgr = std::any::_Manager_external<B>]
  any(_ValueType&& __value)
  ^~~~~~~~~~~~~~~~~~~~~~~~~
<source>:63:23: note: while substituting deduced template arguments into function template 'any' [with _ValueType = const B &, _Tp = (no value), _Mgr = (no value), $3 = (no value), $4 = (no value)]
B(const B& b) : A(b) {       
                  ^
1 error generated.
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)

有趣的是,它在 gcc-7.1 或更高版本中编译。

B 的复制构造函数是否调用 A 的构造函数而不是我想要发生的 A 的复制构造函数?如果是这样,我如何使 B 复制构造函数按照我的预期工作?

ps 这是我用于此的在线编译器的链接https://godbolt.org/z/_22nuW

Fed*_*dor 0

如果是这样,我如何使 B 复制构造函数按照我的预期工作?

我认为最简单的解决方案是替换B(const B& b) : A(b) {}B(const B& b) = default;(或仅删除此行)。然后你的程序将被 Clang 5 接受,演示: https: //gcc.godbolt.org/z/vzE3s16hs

另一个选项是将标准库实现从 GNU 更改libstdc++为 Clang 自己的libc++,这是通过-stdlib=libc++命令行选项完成的。然后您的原始代码将按原样被接受,演示: https: //godbolt.org/z/6ndTdGGE7