c++11 enable_if错误-模板参数重新声明

jdg4fx2g  于 2023-07-01  发布在  其他
关注(0)|答案(2)|浏览(170)

下面是一个例子:

template <class T, typename std::enable_if<!std::is_fundamental<T>::value, int >::type = 0 >
class Calc
{
  public:
    int operator()( const T& v ) const {
        return v.getValue();
    }
};

template <class T, typename std::enable_if<std::is_fundamental<T>::value, int >::type = 0 >
class Calc : CalcBase <T>
{
};

在编译时,我得到以下错误:

c.cpp:26: error: template parameter 'typename std::enable_if<(! std::is_fundamental::value), int>::type <anonymous>'
c.cpp:36: error: redeclared here as 'typename std::enable_if<std::is_fundamental::value, int>::type <anonymous>'

这里的目的是选择Calc的版本,如果传递的模板参数是一个类,则该版本将覆盖基类函数调用运算符。如果传递的参数是基本类型,那么我们选择不覆盖基类功能的Calc版本。你能帮助我了解如何让它工作吗?

kuarbcqp

kuarbcqp1#

我不认为类模板声明与SFINAE一起工作:类模板不像函数模板那样被重载。您声明了两个同名的主类模板,这是不允许的。
方便的是,SFINAE对于您的用例不是必需的:类模板支持部分专门化。您只需使用默认的bool参数,并根据trait是true还是false来专门化类模板。例如:

template <class T, bool = std::is_fundamental<T>::value>
class Calc
{
  public:
    int operator()( const T& v ) const {
        return v.getValue();
    }
};

template <class T>
class Calc<T, false> : CalcBase <T>
{
};
kmb7vmvb

kmb7vmvb2#

将SFINAE与类模板一起使用的一种方法是通过使用SFINAE专门化模板参数的部分专门化。
下面是一个实现问题中描述的类的最小工作示例。
Calc的示例化中,模板参数U要么具有默认类型void,要么具有类型void,但通过enable_if条件为true,或者如果enable_if条件为false,则涉及SFINAE类型错误。
由于U具有void的默认参数,因此导致所有部分专门化的SFINAE类型错误的类型T仍然会导致基于默认参数的类模板的示例化,并避免编译时错误。注意:在这个特定的例子中,其中一个条件必须是true,但是在其他情况下,使用默认参数会有所帮助。

#include <type_traits>

class NonFundamental {
public:
  NonFundamental(int val) : val_(val) {}

  int getValue() {
    return val_;
  }

private:
  int val_;
};

template <typename T>
class Calcbase {};

template <typename T, typename U = void>
class Calc {};

template <typename T>
class Calc<T, typename std::enable_if_t<!std::is_fundamental_v<T>>> {
public:
  int operator()(const T &v) const {
    return v.getValue();
  }
};

template <typename T> 
class Calc<T, typename std::enable_if_t<std::is_fundamental_v<T>>> : Calcbase<T> {
};

int main() {
  Calc<int> calc_obj_1;
  Calc<NonFundamental> calc_obj_2;

  return 0;
}

相关问题