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

标签 c++ templates operator-overloading c++14 sfinae

以下是我可以提出的最有意义的最小程序,以重现该问题的困境。由于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;
}

最佳答案

您可能要使用 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) {}

并修改

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



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

Live example

关于c++ - 如果存在从 `double`到 `T`的转换,SFINAE禁用构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59917228/

相关文章:

C++11 模板 : How to ensure that the type inherits a class?

c++ - 模板部分排序-为什么部分推理在这里成功

c++ - 如果我在 C++ 中实现operator<,我是否也应该实现operator> 和operator==?

c++ - 如何避免这句话在模板 SFINAE 中是错误的?

C++ Eigen : subclassed vector get error in conversion with simple operation

c++ - 为什么 gtest 看不到 == 的定义?

c++ - 为什么在我的代码中将值从构造函数 var 传递到类变量会失败? C++

c++ - 如何从二进制文件安装 memcached 并包含在 c 文件中

C++ 模板和带有方法指针的继承

c++ - 使用模板设置类成员是否为 const