std::any for move-only template where static_assert inside copy-ctor equals compile error,但为什么呢?

std::any for move-only template where static_assert inside copy-ctor equals compile error, but why?

我不明白为什么只能移动的模板不能通过具有 static_assert 的复制函数扩展(如下面的代码)以便与 std::any[= 一起使用19=]

#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

This overload only participates in overload resolution if ... std::is_copy_constructible_v<std::decay_t<ValueType>> is true.

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

考虑以下情况:

foo.h:

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

foo.cpp:

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

main.cpp:

#include "foo.h"

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

    foo(any);

    return 0;
}

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

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

Ok. So do I understand this correct: The copy-ctor gets created and static_assert is being fired because a simple pointer is pointing to the copy-ctor?

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

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