我正在尝试在两个类的对象(Eigen::Vector3d 和 MyVector,Protocol Buffers 消息)之间创建一个转换函数,但我想延迟对函数体的评估,直到函数被引用(此时两者将定义类)。
该函数应该可以在稍后定义这两个类的文件中调用,并且如果从未使用过该函数,则不应导致编译错误。
我有:
#include <Eigen/Core> // defines Eigen::Vector3d
class MyVector {
public: int set_x(int x) { x_ = x; }
private: int x_;
}
void operator<< (MyVector &msg, const Eigen::Vector3d &vec) {
msg.set_x(vec.x());
}
我用作:
MyVector msg;
Eigen::Vector3d vec(1, 2, 3);
msg << vec;
如果函数是在 MyVector 之后定义的,这会很好地工作,但我希望能够定义函数,以便它可以包含在缺少 MyVector 类的翻译单元中。
我可以把函数改成这样:
template<typename Msg>
void operator<< (Msg &msg, ...
但这是 Not Acceptable ,因为它适用于其他消息类别:
quaternion_msg << Eigen::Vector3d(1, 2, 3); // quaternion has xyz but also w!
我希望这会导致构建错误。
是否有某种模板魔术可以做到这一点?如果没有,除了将 MyVector 添加到头文件(或其依赖项)之外,是否有更好的方法来提供此运算符?
最佳答案
您可以在函数模板中使用未定义的类型或函数,只要它们以某种方式依赖于模板参数并且在实例化时定义:非依赖名称在定义函数模板的指针处查找。在实例化时查找从属名称(假设正确实现了两阶段名称查找)。
另一方面,可以使用 SFINAE 来防止使用其他类型成功实例化而不是一小部分选定类型。 :
class MyVector;
template <typename Msg>
typename std::enable_if<std::is_same<Msg, MyVector>::value>::type
operator<< (Msg& msg, Eigen::Vector3d const& vec) {
msg.set_x(vec.x);
}
type
的 std::enable_if<F, T>
仅在 F
时定义是true
(并且 T
默认为 void
)。自 std::is_same<Msg, MyVector>::value
变成 true
仅当 Msg
是MyVector
此运算符仅在使用 MyVector
实例化时才被定义.另一方面,它在实例化时得到定义 MyVector
希望得到定义。
但是,由于 MyVector
在接口(interface)中命名,虽然不需要定义,但需要声明它的名称。如果 MyVector
可以避免这种需要可以专门化一个特征,在这种情况下命名 MyVector
一个类型可以被延迟,直到它被定义并且特性被专门化。如果MyVector
,做这样的事情可能很重要实际上恰好是一个带有默认参数的模板,因为这些参数不能被前向声明。
关于c++ - 如果从不使用该函数,您可以在 C++ 模板函数中使用未定义的类型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20599890/