I'm trying to get my head around C++ templates and copy semantics. I understand why I can't call assign1
(It asks for rvalue references and I'm providing an lvalue ref) But then why am I able to call assign2
which imposes the same constraints?
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...
}
Given assign1<int>(r);
, you're specifying the template argument explicitly, then the parameter type of assign1
would be int&&
, as you said, it's rvalue-reference and can't be bound with lvalue.
Given assign2<int>(r);
, you're specifying the 1st template argument A
as int
, the parameter pack Args
will be deduced from the function argument r
. Note that it's not rvalue-reference but forwarding reference , which could accpet both lvalues and rvalues. (Depending on the function arguments are lvalues or rvalues, according to the type deduction result, the function parameter type would be lvalue-reference or rvalue-reference.)
Given assign3<int>(r);
, you're specifying only the 1st template argument A
, but the 2nd parameter parameter B
can't be deduced from function argument and the calling fails.
If you want to make the function template accepting rvalues only, you can add static_assert
like
template<typename A, typename... Args>
void assign2(Args&& ...) {
static_assert(((!std::is_lvalue_reference_v<Args>) && ...), "must be rvalue");
}
Or apply SFINAE .
template<typename A, typename... Args>
std::enable_if_t<((!std::is_lvalue_reference_v<Args>) && ...)> assign2(Args&& ...) {
}
Or add another overload taking lvalue-references and mark it as delete
. (This approach works only when all the arguments are lvalues.)
template<typename A, typename... Args>
void assign2(Args& ... arguments) = delete;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.