简体   繁体   中英

C++ template function unused typename

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

LIVE

Or apply SFINAE .

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

LIVE

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;

LIVE

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM