如何有条件地声明类模板上的成员重载?

问题描述 投票:0回答:1

我正在尝试根据模板参数使用

std::enable_if
有条件地定义类模板上的成员重载:

#include <cstddef>
#include <memory>
#include <math.h>
#include <iostream>
#include <type_traits>

//------------------------------------------------------------------------------
class MyDouble {
 public:
    MyDouble(double value_) : value(value_) { /* ... */ };

    operator double() const { return value; };

 protected:
    double value;
};

//------------------------------------------------------------------------------
class Base {
 public:
    explicit Base(double v1_ = 0.0, double v2_ = 0.0, double v3_ = 0.0);

    virtual ~Base() = default;

    virtual void update(double d1, double d2, double d3);

    double v1;
    double v2;
    double v3;

};

Base::Base(double v1_, double v2_, double v3_) :
    v1(v1_), v2(v2_), v3(v3_) {
        /* ... */
}

void Base::update(double d1, double d2, double d3) {
    v1 += d1;
    v2 += d2;
    v3 += d3;
}

//------------------------------------------------------------------------------
template < typename Arg = double >
class Derived : public Base {
 public:
    explicit Derived(Arg extra_);

    virtual ~Derived() = default;

    void update(double d1, double d2, double d3) override;

    // overload, declared only when Arg == MyDouble
    template < typename T = Arg, typename = typename std::enable_if< std::is_same< Arg, MyDouble >::value >::type >
    void update(double d1, double d2, double d3, double extra);

    Arg extra;
};

template < typename Arg >
Derived< Arg >::Derived(Arg extra_) :
    Base(0.0, 0.0, 0.0),
    extra(extra_) {
        /* ... */
}

template < typename Arg >
void Derived< Arg >::update(double d1, double d2, double d3) {
    std::cout << "update" << std::endl;
    Base::update(d1, d2, d3);
}

template < typename Arg >
template < typename T, typename >
void Derived< Arg >::update(double d1, double d2, double d3, double extra) {
    std::cout << "MyDouble update" << std::endl;
    // ...
    Base::update(d1, d2, d3);
}


//------------------------------------------------------------------------------
int main(int argc, char const *argv[]) {

    Derived< double > foo(5);
    Derived< MyDouble > bar(10);  

    return 0;
}

但是,我明白了

In instantiation of ‘class Derived<double>’:
[...]
error: no type named ‘type’ in ‘struct std::enable_if<false, void>’

这至少告诉我,情况正在接受检查。实现所需行为的正确 SFINAE 语法是什么?

c++ templates overloading sfinae
1个回答
0
投票

您的

enable_if
不依赖于函数的模板参数,即
T
。没有替代,因此也没有替代失败。

更改为:

template <typename T = Arg, 
          typename = typename std::enable_if<std::is_same<T, MyDouble >::value >::type >
//                                                        ^
© www.soinside.com 2019 - 2024. All rights reserved.