I am writing tests on Eigen matrices using Google\'s testing framework Google-Mock, as already discussed in another question.
With the followi
The problems you encounter are overload resolution problems.
google test implements a template function
namespace testing { namespace internal {
template
void PrintTo(const T& value, std::ostream *o) { /* do smth */ }
} }
The Eigen library defines a printer function that is based on derivation. Hence
struct EigenBase { };
std::ostream& operator<< (std::ostream& stream, const EigenBase& m) { /* do smth */ }
struct Eigen : public EigenBase { };
void f1() {
Eigen e;
std::cout << e; // works
}
void f2() {
Eigen e;
print_to(eigen, &std::cout); // works
}
Both do have questionable design.
Google Test should not provide an implementation of PrintTo
but should instead check at compile time whether the user provides a PrintTo
and otherwise call a different default printing function PrintToDefault
. The PrintTo
provides is a better match than the one you provided (according to overload resolution).
on the other hand Eigen's operator<<
is based on derivation and a template function will also be preferred by overload resolution.
Eigen could provide a CRTP base class that inherits the operator<<
which a better matching type.
What you can do is inherit from eigen and provide a CRTP overload to your inherited class avoiding the issue.
#include
#include
class EigenBase {
};
std::ostream &operator<<(std::ostream &o, const EigenBase &r) {
o << "operator<< EigenBase called";
return o;
}
template
void print_to(const T &t, std::ostream *o) {
*o << "Google Print To Called";
}
class EigenSub : public EigenBase {};
template
struct StreamBase {
typedef T value_type;
// friend function is inline and static
friend std::ostream &operator<<(std::ostream &o, const value_type &r) {
o << "operator<< from CRTP called";
return o;
}
friend void print_to(const value_type &t, std::ostream *o) {
*o << "print_to from CRTP called";
}
};
// this is were the magic appears, because the oeprators are actually
// defined with signatures matching the MyEigenSub class.
class MyEigenSub : public EigenSub, public StreamBase {
};
TEST(EigenBasePrint, t1) {
EigenBase e;
std::cout << e << std::endl; // works
}
TEST(EigenBasePrint, t2) {
EigenBase e;
print_to(e, &std::cout); // works
}
TEST(EigenSubPrint, t3) {
EigenSub e;
std::cout << e << std::endl; // works
}
TEST(EigenCRTPPrint, t4) {
MyEigenSub e;
std::cout << e << std::endl; // operator<< from CRTP called
}
TEST(EigenCRTPPrint, t5) {
MyEigenSub e;
print_to(e, &std::cout); // prints print_to from CRTP called
}