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

c++11 enable_if error - template parameter re-declaration

本文关键字:新声明 声明 参数 enable if 错误 c++11      更新时间:2023-10-16

我试图得到以下代码编译:

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版本。你能帮我理解一下我怎么才能让它工作吗?

我不认为类模板声明与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>
{
};

在类模板中使用SFINAE的一种方法是通过局部专门化,使用SFINAE专门化模板参数。

这是一个最小的工作示例,实现了问题中描述的类。

Calc的实例化中,模板参数U要么具有默认类型void,要么具有类型void,但通过enable_if条件为true,或者如果enable_if条件为false,则涉及SFINAE类型错误。

由于U具有void的默认参数,类型T导致所有部分专门化的SFINAE类型错误仍然会导致基于默认参数的类模板的实例化,从而避免编译时错误。注意:在这种特殊情况下,其中一个条件必须是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;
}