以下编译正常:
#include <iostream>
#include <vector>
class Point : public std::vector<double>
{
public:
Point() = default;
};
class MyClass
{
public:
template <typename T>
operator T() const { return T(); }
};
int main()
{
MyClass myClass;
Point test = myClass;
return 0;
}
但是,如果我有一个模板化的构造函数,它不会:
#include <iostream>
#include <vector>
class Point : public std::vector<double>
{
public:
Point() = default;
template <typename TVector>
Point(const TVector& v)
{
(*this)[0] = v[0]; // compiler error on this line (saying no operator[] for MyClass, but the point is that this function is used instead of the type conversion function)
}
};
class MyClass
{
public:
template <typename T>
operator T() const { return T(); }
};
int main()
{
MyClass myClass;
Point test = myClass;
return 0;
}
我无法更改Point
类(添加第二个默认构造函数参数或类似的东西),那么有没有办法只更改MyClass
以使其工作?
答案 0 :(得分:1)
当operator[]
TVector
时,您可以使用SFINAE禁用构造函数
template <typename TVector, typename=decltype(std::declval<const TVector&>()[0])>
Point(const TVector& v)
当尝试评估第二个typename
时,编译器必须推断出TVector::operator[]
返回的内容。当它不能时,它会从重载决策中抛出构造函数。
如果您想稍微详细说明,可以使用enable_if
在Point
template <typename...>
using void_t = void;
template <typename T, typename = void>
struct HasIndexOperator : std::false_type {};
template <typename T>
struct HasIndexOperator<T,
void_t<decltype(std::declval<const T&>()[0])>> : std::true_type {};
然后你的构造函数变为:
template <typename TVector,
typename=std::enable_if_t<HasIndexOperator<TVector>{}>>
Point(const TVector& v)
答案 1 :(得分:-1)
像这样的模板构造函数
template <typename TVector>
Point(const TVector& v)
将作为用户定义的构造函数工作,接受任何不属于Point
类型的东西(仍然由隐含定义的复制构造函数处理)。
与
Point point = myclass;
编译器正在查找模板化构造函数,不执行任何转换并尝试在operator[]
上调用MyClass
。
当您为非向量禁用模板化构造函数(如Ryan所建议)时,唯一剩下的就是非模板复制构造函数,隐含地声明为
Point(const Point& );
编译器将执行从MyClass
到Point
的转换,一切都将编译。