Ниже приводится минимальная значимая программа, которую я мог бы придумать, чтобы воспроизвести мое затруднительное положение для этого вопроса. Программа не может быть скомпилирована из-за конфликта между конструкторами 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;
}