c++ - 意外丢失隐式声明的复制/移动构造函数

标签 c++ copy-constructor c++17 move-constructor implicit-declaration

考虑以下因素:

#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<C()> f_;

C 是不完整类型。在 F 中,C 替换模板参数 R,然后将其用作 std::is_invocable_r_v 的模板参数>。标准不允许使用不完整类型作为 std::is_invocable_r_v 的模板参数,这会导致未定义的行为。未定义的行为包括编译器在编译期间的任意行为。


请注意,我并不完全确定我的答案,主要是因为模板化的 F::F 构造函数及其模板化的 operator() 都没有被实例化。

关于c++ - 意外丢失隐式声明的复制/移动构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49286779/

相关文章:

c++ - 有没有办法在 C++ 编译器中禁用复制省略

c++ - 测试 std::common_type 是否存在

c++ - 避免在 make_unique/make_shared/emplace/etc 中对使用聚合初始化的结构进行额外移动

c++ - 复制构造函数的调用

c++ - 抽象类中的复制控件

c++ - 引入std::enable_if后出现"No match"错误

c++ - 获取右值引用的地址是什么意思?

c++ - CMake 的导出如何知道目标是什么版本?

c++ - OpenGL 上下文创建从不选择像素格式

c++ - 使用 C++ 在 iOS 中创建目录/文件