使用std :: enable_if作为函数参数与模板参数有什么区别?

What is the difference between using std::enable_if as function argument vs template argument?

本文关键字:参数 什么 区别 函数 enable std if 使用      更新时间:2023-10-16

我想知道使用 std::enable_if作为函数参数与模板参数有什么区别?

i具有以下2个函数模板:

#include <type_traits>
template<typename T>
void f_function(T, typename std::enable_if_t<std::is_pod<T>::value, int> = 0)
{
}
template<typename T, typename = typename std::enable_if_t<std::is_pod<T>::value>>
void f_template(T)
{
}
int main()
{
  int x = 1;
  f_function(x);
  f_template(x);
}

产生以下组件(如https://godbolt.org/g/on4rya):

main:
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $16, %rsp
        movl    $1, -4(%rbp)
        movl    -4(%rbp), %eax
        movl    $0, %esi
        movl    %eax, %edi
        call    void f_function<int>(int, std::enable_if<std::is_pod<int>::value, int>::type)
        movl    -4(%rbp), %eax
        movl    %eax, %edi
        call    void f_template<int, void>(int)
        movl    $0, %eax
        leave
        ret
void f_function<int>(int, std::enable_if<std::is_pod<int>::value, int>::type):
        pushq   %rbp
        movq    %rsp, %rbp
        movl    %edi, -4(%rbp)
        movl    %esi, -8(%rbp)
        nop
        popq    %rbp
        ret
void f_template<int, void>(int):
        pushq   %rbp
        movq    %rsp, %rbp
        movl    %edi, -4(%rbp)
        nop
        popq    %rbp
        ret

除了明显的区别外,f_function具有2个函数参数和f_template具有2个模板参数,它们之间有什么区别?一个人有任何特殊用途吗?

作为琐碎的例子,您可以做到这一点:

int main() {
    // f_function(std::string{}); // (1)
    // f_template<std::string>(std::string{}); // (2)
    f_template<std::string, void>(std::string{});
}

(1)(2) 没有出于明显的原因(std::string不是接受类型),即使Tf_template也可以与技巧一起使用不是POD类型。


有效的选择是:

template<typename T, std::enable_if_t<std::is_pod<T>::value>* = nullptr>
void f_template(T)
{ }

另一个可能是:

template<typename T>
std::enable_if_t<std::is_pod<T>::value>
f_template(T)
{ }

涉及参数包作为后卫的更晦涩的

template<typename T, typename..., typename = typename std::enable_if_t<std::is_pod<T>::value>>
void f_template(T)
{ }

所有这些都按预期工作,您无法围绕它们工作(至少,我不知道该怎么做,但是也许有人会带来一个很好的技巧)。

相关文章: