0

我不明白为什么只有移动模板不能通过具有 a static_assert(如下面的代码)的 copy-ctor 来扩展,以便与std::any

#include <any>
#include <cassert>

namespace detail{
template<typename T=int>
struct MoveOnly
{
    MoveOnly() = default;
    MoveOnly(MoveOnly const&) {static_assert(sizeof(T)!=sizeof(T),"");}
    MoveOnly(MoveOnly &&) = default;
    MoveOnly &operator=(MoveOnly const&) {static_assert(sizeof(T)!=sizeof(T),"");}
    MoveOnly &operator=(MoveOnly &&) = default;
};
}
using MoveOnly = detail::MoveOnly<>;
static_assert(std::is_copy_constructible<MoveOnly>::value,"");

int main() {
    MoveOnly a;
    //std::any any(std::move(a)); //<- compile error
    return 0;
}

std::any::any它说 ctor #4

此重载仅在 ... std::is_copy_constructible_v<std::decay_t<ValueType>> 为真时参与重载决议。

据我所见std::is_copy_constructible<MoveOnly>::value,给出了 true 并且永远不会调用 copy-ctor 。那么编译器怎么可能仍然抱怨static_assert内部的copy-ctor呢?

4

1 回答 1

1

考虑以下情况:

富.h:

void foo(const std::any& v);

foo.cpp:

void foo(const std::any& v) {
  std::any tmp = v;
}

主.cpp:

#include "foo.h"

int main() {
    MoveOnly a;
    std::any any(std::move(a));

    foo(any);

    return 0;
}

在 内部main.cpp,没有办法知道是否foo()会复制v,所以我们别无选择,必须有一个可用的复制构造函数,以防万一它可能需要被调用。

编辑:要解决评论中提到的问题:

好的。那么我是否理解正确:复制ctor被创建并且static_assert被触发,因为一个简单的指针指向复制ctor?

本质上,是的。一旦指针指向一个函数,该函数就必须存在,并且使该函数存在将触发它的代码生成,包括评估其中的任何static_assert()内容。

在您的理解中唯一有点偏离的是指针不只是为了它而存在。它在那里是因为它很有可能被用来调用指向的函数。也许它会在 LTO 期间得到优化,但为时已晚;代码生成到那时完成

于 2019-11-11T21:39:00.607 回答