SFINAE禁用构造函数,如果存在从double到T的转换

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

以下是我可以提出的最小的有意义的程序,以重现此问题的困境。由于LinearForm<double>的构造函数之间的冲突,程序无法编译。为解决此冲突,我希望仅当不存在从LinearForm<V>::LinearForm(double)double的转换时才启用V。我怎样才能做到这一点? (并且它将解决构造函数之间的冲突吗?)

#include <type_traits>
#include <array>

template<int N>
struct Vector{
    std::array<double,N> coords;

    Vector(std::array<double,N> coords) : coords(coords) {}

    // implicit conversions between scalar and Vector<1>
    template<int Nd = N, std::enable_if_t<Nd==1>>
    Vector(double scalar) : coords(scalar) {}
    template<int Nd = N, std::enable_if_t<Nd==1>>
    operator double() const {return coords[0];}

    double dot(Vector<N> u) const {
        double acc = 0;
        for(int i=0; i<N; i++){
            acc += coords[i]*u.coords[i];
        }
        return acc;
    }

    static Vector<N> zero(){ return Vector<N>(std::array<double,N>{}); }
};

template<typename V> // V is domain element type i.e. LinearForm maps from V to double
struct LinearForm {
    V v;
    LinearForm(V v) : v(v) {}

    //template<typename Vd=V, typename = std::enable_if_t</* WHAT TO PUT IN HERE */>>
    LinearForm(double v) : LinearForm(V::zero())
    {
        if(v != 0){
            throw std::runtime_error("LinearForm cannot be non-zero constant.");
        }
    }
    double operator()(V u){return u.dot(v);}
};

int main()
{
    LinearForm<Vector<2>> lf(Vector<2>({1,2}));
    LinearForm<Vector<2>> zf = 0;

    LinearForm<double> slf = 0;

    auto u = Vector<2>({3,4});
    lf(u); // returns some value
    zf(u); // should return zero for any u

    return 0;
}
c++ templates operator-overloading c++14 sfinae
2个回答
1
投票
std::is_convertible

要编译您的代码,我还需要添加两点:

template <typename Vd=V,
          typename std::enable_if_t<std::is_convertible<double, Vd>::value>::type* = nullptr>
LinearForm(double v) : LinearForm(V::zero())
{
    if(v != 0){
        throw std::runtime_error("LinearForm cannot be non-zero constant.");
    }
}

和修改

LinearForm(int value) : v(value) {}

to

template<int Nd = N, std::enable_if_t<Nd==1>>
Vector(double scalar) : coords(scalar) {}

template<int Nd = N> Vector(double scalar) : coords({scalar}) {}


0
投票
是您要搜索的内容
© www.soinside.com 2019 - 2024. All rights reserved.