基于模板类型指针的条件函数行为

Posted

技术标签:

【中文标题】基于模板类型指针的条件函数行为【英文标题】:Conditional function behavior based on pointer-ness of template type 【发布时间】:2018-12-03 09:30:54 【问题描述】:

我正在尝试为模板类提出一个成员函数:

在模板类型是指针的情况下做一些事情 对非指针什么都不做

不确定 SFINAE 是否适用于此,因为我需要这两个版本,因为我在类本身中调用它们。请注意,我仅限于 C++11。

template < typename T_ = T, typename = std::enable_if_t <!std::is_pointer<T_> > >
void SomeFunction()

    // Do nothing

template < typename T_ = T, typename = std::enable_if_t < std::is_pointer<T_> > >
void SomeFunction()

    // Do sth

编译器报错 error C2535: member function already defined or declared

【问题讨论】:

***.com/questions/53351945/… 另一个复杂的 SFINAE 可以用 C++17 变得非常简单if constexpr 【参考方案1】:

问题是默认模板参数不是function template signature 的一部分。这两个SomeFunctions 被认为是相同的,然后导致重新声明错误。

两个函数模板被认为是等价的

它们在同一范围内声明 他们有相同的名字 它们具有相同的模板参数列表 返回类型和参数列表中涉及模板参数的表达式是等价的

您可以在返回类型中使用它们,例如(针对 C++11)

template <typename T_ = T>
typename std::enable_if<!std::is_pointer<T_>::value>::type SomeFunction()

    // Do nothing

template <typename T_ = T>
typename std::enable_if<std::is_pointer<T_>::value>::type SomeFunction()

    // Do sth

LIVE

或者在非类型模板参数列表中使用它们,例如(针对 C++11)

template < typename T_ = T, typename std::enable_if<!std::is_pointer<T_>::value>::type* = nullptr>
void SomeFunction()

    // Do nothing
    std::cout << "Do nothing\n";

template < typename T_ = T, typename std::enable_if<std::is_pointer<T_>::value>::type* = nullptr>
void SomeFunction()

    // Do sth
    std::cout << "Do sth\n";

LIVE

【讨论】:

太棒了!更简洁的版本是template &lt; typename T_ = T, typename std::enable_if_t &lt; !std::is_pointer&lt;T_&gt; &gt;* = nullptr&gt;【参考方案2】:

问题在于两个函数模板声明是等价的,因此编译器认为您的代码包含 2 个函数定义的唯一函数。

函数模板等效性在[temp.over.link]/6 和[temp.over.link]/7 中进行了描述。

在您的具体情况下,问题在于这个等价性没有考虑到默认模板参数。

如果你添加一个默认的模板参数,这两个功能将不等效:

   template < typename T_ = T
            , typename = std::enable_if_t <!std::is_pointer<T_> > >
    void SomeFunction()
    
        // Do nothing
    
    template < typename T_ = T
             , class=void
             , typename = std::enable_if_t < std::is_pointer<T_> > >
    void SomeFunction()
    
        // Do sth
    

【讨论】:

以上是关于基于模板类型指针的条件函数行为的主要内容,如果未能解决你的问题,请参考以下文章

成员函数指针值上的 Consexpr - 未定义的行为?

Kotlin学习—— 基本语法,函数,变量,字符串模板,条件表达式,null,类型检测,for,while,when,区间,集合

通过三元条件选择的指针调用函数

简化条件表达式之以多态取代条件表达式(Replace Conditional with Polymorphism)

Kotlin空安全总结 ( 变量可空性 | 手动空安全管理 | 空安全调用操作符 | 非空断言操作符 | 空合并操作符 | 空指针异常处理 | 先决条件函数判空 )

解密C++多态属性