c++ - 如果从不使用该函数,您可以在 C++ 模板函数中使用未定义的类型吗?

标签 c++

我正在尝试在两个类的对象(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);
}

typestd::enable_if<F, T>仅在 F 时定义是true (并且 T 默认为 void )。自 std::is_same<Msg, MyVector>::value变成 true仅当 MsgMyVector此运算符仅在使用 MyVector 实例化时才被定义.另一方面,它在实例化时得到定义 MyVector希望得到定义。

但是,由于 MyVector在接口(interface)中命名,虽然不需要定义,但需要声明它的名称。如果 MyVector 可以避免这种需要可以专门化一个特征,在这种情况下命名 MyVector一个类型可以被延迟,直到它被定义并且特性被专门化。如果MyVector,做这样的事情可能很重要实际上恰好是一个带有默认参数的模板,因为这些参数不能被前向声明。

关于c++ - 如果从不使用该函数,您可以在 C++ 模板函数中使用未定义的类型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20599890/

相关文章:

c++ - OpenGL数据传输到显卡

c++ - 在 Windows-8 64 位中通过 eclipse luna 运行 valgrind/其他内存检查

c++ - 在 C++ 中计算毫秒的可移植方法?

c++ - C++:指向 vector (及其元素)的指针是否稳定,因为 vector 将在内存中迁移以适应它们增长时容纳的更多元素?

php - 如何解释at()函数; substr()函数;伪代码中的exist()函数

c# - 如何为 C# 项目生成 .tlh 文件

c++ - boost::variant 隐式转换为字符串

c++ - 你能帮我理解 "significant digits"在 float 学中的含义吗?

c++ - 在 C++ 中调用 VB 的 CreateObject 方法

c++如何释放和删除指向对象的二维数组