【问题标题】: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

【问题讨论】:

标签: c++ c++11 templates sfinae


【解决方案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
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多