geometry2
geometry2 copied to clipboard
[windows] Fix ambiguous call for tf2::convert on MSVC
- rework ambiguous call on MSVC.
Forward port of #444 to noetic
@seanyen The patch from #444 doesn't forward port to noetic successfully. Could you take a look at why?
I don't want to be disrespectful, but I pointed out the problem at multiple places. Please correct me if I'm wrong. The error message from the build is exactly the same as in #430:
11:56:08 test_convert.cpp:(.text._ZN3tf24impl9ConverterILb0ELb0EE7convertINS_10QuaternionEN5Eigen10QuaternionIdLi0EEEEEvRKT_RT0_[_ZN3tf24impl9ConverterILb0ELb0EE7convertINS_10QuaternionEN5Eigen10QuaternionIdLi0EEEEEvRKT_RT0_]+0x45): undefined reference to `void tf2::fromMsg<geometry_msgs::Quaternion_<std::allocator<void> >, Eigen::Quaternion<double, 0> >(geometry_msgs::Quaternion_<std::allocator<void> > const&, Eigen::Quaternion<double, 0>&)'
11:56:08 collect2: error: ld returned 1 exit status
IMHO, the whole conversion stuff boils down to something like (taken from here)
#include <iostream>
namespace msgs {
struct A_msg {
A_msg(){} // for clang
};
}
namespace datatypes {
struct B_dt {};
}
namespace tf2 {
template <class A, class B>
void fromMsg(const A&, B&);
template <class A, class B>
void convert(const A& a, B& b) {
fromMsg(a, b);
}
//template<>
void fromMsg(const msgs::A_msg& a, datatypes::B_dt& b) {}
}
int main () {
const msgs::A_msg a;
datatypes::B_dt b;
tf2::convert(a, b);
std::cout << "Hello, world!\n";
}
Compilation/linking fails with GCC, Clang and MSVC (with /permissive-
flag set). If you uncomment the template<>
statement or if you reorder the tf2
namespace
namespace tf2 {
void fromMsg(const msgs::A_msg& a, datatypes::B_dt& b) {}
template <class A, class B>
void fromMsg(const A&, B&);
template <class A, class B>
void convert(const A& a, B& b) {
fromMsg(a, b);
}
}
it works fine.
When the conversion is requested, tf2::convert()
uses the templated forward declaration for tf2::fromMsg()
in tf2/transform_functions.h.
The point is that the corresponding function is not defined as a template specialization in tf2_eigen.h, but as a 'classic' overload. So, this correct overloaded function will only be chosen if it is defined before the generic forward declaration. Otherwise, these linking errors occur. The users have to take care on how they order their header #include
s which is very error-prone.
@tfoote Sorry this is out of my radar. I will be checking this one soon.