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");
}

LIVE

或申请SFINAE.

template<typename A, typename... Args>
std::enable_if_t<((!std::is_lvalue_reference_v<Args>) && ...)> assign2(Args&& ...) {
}

LIVE

或者添加另一个采用左值引用的重载并将其标记为 delete。 (此方法仅在所有参数均为左值时有效。)

template<typename A, typename... Args> 
void assign2(Args& ... arguments) = delete;

LIVE