折叠表达式和参数包:static_assert 内 Args&& 和 Args 之间的区别

Fold expressions and parameter pack: difference betwen Args&& and Args inside static_assert

本文关键字:Args 区别 assert 之间 参数 表达式 static 折叠      更新时间:2023-10-16

这段代码来自
https://en.cppreference.com/w/cpp/language/fold

template<typename T, typename... Args>
void push_back_vec(std::vector<T>& v, Args&&... args){
static_assert((std::is_constructible_v<T, Args&&> && ...));
(v.push_back(std::forward<Args>(args)), ...);
}

我不明白为什么静态断言检查Args&&而不是Args

这是针对像这样的极端情况完成的,当你只有类型声明但没有定义(std::is_constructible不完整的类型 - 在这种情况下is_constructible是 UB(:

struct B;
struct A {
A(const A&) = default;
A(const B&) {}
A(A&&) = default;
A() = default;
};
B&& getB();
template<typename T, typename... Args>
void push_back_vec(std::vector<T>& v, Args&&... args){
static_assert((std::is_constructible_v<T, Args&&> && ...));
(v.push_back(std::forward<Args>(args)), ...);
}
template<typename T, typename... Args>
void push_back_vec2(std::vector<T>& v, Args&&... args){
static_assert((std::is_constructible_v<T, Args> && ...));
(v.push_back(std::forward<Args>(args)), ...);
}
int main(int argc, char* argv[])
{
std::vector<A> a;
push_back_vec(a, A(), A());
push_back_vec2(a, A(), A());
A aa;
push_back_vec(a, aa, aa, A());
push_back_vec2(a, aa, aa, A());

push_back_vec(a, getB());
// code below won't compile
//push_back_vec2(a, aa, A(), getB());
}

现场示例