C++ 模板函数未使用的类型名
C++ template function unused typename
我正在努力了解 C++ 模板和复制语义。
我明白为什么我不能调用 assign1
(它要求右值引用,而我提供左值引用)
但是为什么我可以调用 assign2
来施加相同的约束?
template<typename... Args>
void assign1(Args&& ... arguments) { }
template<typename A, typename... Args>
void assign2(Args&& ... arguments) { }
template<typename A, typename B, typename... Args>
void assign3(Args&& ... arguments) { }
int main() {
const int r = 2;
assign1<int>(r); // no matching function for call to...
assign2<int>(r); // ok!
assign3<int>(r); // no matching function for call to...
}
鉴于 assign1<int>(r);
,您明确指定了模板参数,那么 assign1
的参数类型将是 int&&
,如您所说,它是右值引用并且可以' t 与左值绑定。
给定 assign2<int>(r);
,您将第一个模板参数 A
指定为 int
,将从函数参数 [=20] 推导出参数包 Args
=].请注意,它不是右值引用,而是 forwarding reference,它可以同时接受左值和右值。 (根据函数参数是左值还是右值,根据类型推导结果,函数参数类型为左值引用或右值引用。)
给定 assign3<int>(r);
,您仅指定了第一个模板参数 A
,但是第二个参数参数 B
无法从函数参数中推导出来,调用失败。
如果你想让函数模板只接受右值,你可以添加static_assert
like
template<typename A, typename... Args>
void assign2(Args&& ...) {
static_assert(((!std::is_lvalue_reference_v<Args>) && ...), "must be rvalue");
}
或申请SFINAE.
template<typename A, typename... Args>
std::enable_if_t<((!std::is_lvalue_reference_v<Args>) && ...)> assign2(Args&& ...) {
}
或者添加另一个采用左值引用的重载并将其标记为 delete
。 (此方法仅在所有参数均为左值时有效。)
template<typename A, typename... Args>
void assign2(Args& ... arguments) = delete;
我正在努力了解 C++ 模板和复制语义。
我明白为什么我不能调用 assign1
(它要求右值引用,而我提供左值引用)
但是为什么我可以调用 assign2
来施加相同的约束?
template<typename... Args>
void assign1(Args&& ... arguments) { }
template<typename A, typename... Args>
void assign2(Args&& ... arguments) { }
template<typename A, typename B, typename... Args>
void assign3(Args&& ... arguments) { }
int main() {
const int r = 2;
assign1<int>(r); // no matching function for call to...
assign2<int>(r); // ok!
assign3<int>(r); // no matching function for call to...
}
鉴于 assign1<int>(r);
,您明确指定了模板参数,那么 assign1
的参数类型将是 int&&
,如您所说,它是右值引用并且可以' t 与左值绑定。
给定 assign2<int>(r);
,您将第一个模板参数 A
指定为 int
,将从函数参数 [=20] 推导出参数包 Args
=].请注意,它不是右值引用,而是 forwarding reference,它可以同时接受左值和右值。 (根据函数参数是左值还是右值,根据类型推导结果,函数参数类型为左值引用或右值引用。)
给定 assign3<int>(r);
,您仅指定了第一个模板参数 A
,但是第二个参数参数 B
无法从函数参数中推导出来,调用失败。
如果你想让函数模板只接受右值,你可以添加static_assert
like
template<typename A, typename... Args>
void assign2(Args&& ...) {
static_assert(((!std::is_lvalue_reference_v<Args>) && ...), "must be rvalue");
}
或申请SFINAE.
template<typename A, typename... Args>
std::enable_if_t<((!std::is_lvalue_reference_v<Args>) && ...)> assign2(Args&& ...) {
}
或者添加另一个采用左值引用的重载并将其标记为 delete
。 (此方法仅在所有参数均为左值时有效。)
template<typename A, typename... Args>
void assign2(Args& ... arguments) = delete;