【发布时间】:2018-03-14 20:05:49
【问题描述】:
考虑以下几点:
#include <type_traits>
template <typename>
struct F;
template <typename R, typename... As>
struct F<R(As...)>
{
template <typename F_, std::enable_if_t<
std::is_invocable_r_v<R, std::decay_t<F_>, As...>>*...>
F(F_&&) {}
F() = default;
template <typename... As_, std::enable_if_t<
std::is_invocable_v<void(As&&...), As_...>>*...>
R operator()(As_&&...)
{ return R(); }
};
struct C
{
F<C()> f_;
// C(C&&) = default; // <<< 1
};
int main() {
F<C(int)> x;
auto y = x;
}
gcc 7.3.0 编译失败(在std::is_invocable_r 深处):
error: invalid use of incomplete type
‘struct std::__or_<std::is_void<C>, std::is_convertible<C, C> >’
clang 5.0.1 也是如此:
error: no type named 'type' in
'std::__or_<std::is_void<C>, std::is_convertible<C, C> >'
由此我推断C 缺少移动和复制构造函数。事实上,如果我们取消注释它的移动构造函数 (1),这段代码就会编译。
我相信隐式声明它们的要求得到了满足。为什么不呢?
【问题讨论】:
-
我不确定,但我认为通过在
F中声明一个移动构造函数,您会隐式删除F的复制构造函数,进而隐式删除C的复制构造函数.我会尝试实现(或defaulting/deleteing)F的复制构造函数、复制/移动赋值运算符和析构函数以遵循 5 的规则。 -
@DanielLangr 啊,好点子。
-
F中的移动构造函数是隐式定义的。 -
在
F<C()> f_;处,C是一个不完整的类型,对应F中的R模板参数,它被用作std::is_invocable_r_v的模板参数。std::is_invocable_r_v的模板参数不能是不完整的类型。但我不确定这是否是报告问题的原因。如果是,那么你有未定义的行为。
标签: c++ copy-constructor c++17 move-constructor implicit-declaration