Google测试声明模板化方法PrintTo
:
template <typename T>
void PrintTo(const T& value, ::std::ostream* os);
有几个没有模板的重载。我还为自定义类型添加了重载。
我的问题是我不喜欢谷歌提供的默认模板化方法,而是我想像这样实现它:
template<typename T>
void PrintTo(const T &val, ::std::ostream *os)
{
QString str;
QDebug(&str) << val;
*os << qUtf8Printable(str);
}
这将解决许多Qt类型的问题。我无法改变谷歌测试代码中的实现。我需要在我自己的代码中重新实现它。
使用我的模板方法我得到了这个编译错误:
include/gtest/gtest-printers.h:707:22: error: call of overloaded ‘PrintTo(const QChar&, std::ostream*&)’ is ambiguous
PrintTo(value, os);
^
include/gtest/gtest-printers.h:707:22: note: candidates are:
include/gtest/gtest-printers.h:454:6: note: void testing::internal::PrintTo(const T&, std::ostream*) [with T = QChar; std::ostream = std::basic_ostream<char>]
void PrintTo(const T& value, ::std::ostream* os) {
^
In file included from tstgoogletest.cpp:51:0:
googletestqttypes.h:24:6: note: void PrintTo(const T&, std::ostream*) [with T = QChar; std::ostream = std::basic_ostream<char>]
void PrintTo(const T &val, ::std::ostream *os)
^
是否可以使用我的自定义实现“重载”模板化方法而不列出我想要使用的每种类型?
QDebug已经支持了数千种类型,我不想错过这个功能!
答案 0 :(得分:1)
问题是编译器无法执行重载,因为您的函数签名与google完全相同。您可以创建一个新类型来强制重载,例如:
#include <iostream>
// Google version
template <class T>
void print(const T& value, std::ostream& os) {
os << "Google print: " << value << std::endl;
}
// My wrapper type
template <class T>
struct PrintWrap {
const T& value_;
PrintWrap(const T& value): value_(value){}
};
template <class T>
PrintWrap<T> printWrap(const T& value) {
return PrintWrap<T>(value);
}
template <class T>
void print(const PrintWrap<T>& printWrap, std::ostream& os) {
os << "My special print: " << printWrap.value_ << std::endl;
}
int main() {
std::string value = "Hallo world";
print(printWrap(value), std::cout);
// your code goes here
return 0;
}
如果你无法控制调用代码,你可以重载printWrap中所需的必要函数,例如operator ==在下面重载,因为库函数(checkEqualTo)需要这样:
#include <iostream>
// Google version
template <class T>
void print(const T& value, std::ostream& os) {
os << "Google print: " << value << std::endl;
}
// My wrapper type
// :NOTE Overload what is required by Google, in this
// case lets assume operator== as example
template <class T>
struct PrintWrap {
const T& value_;
PrintWrap(const T& value): value_(value){}
friend bool operator==(const PrintWrap& lhs, const PrintWrap& rhs) {
return lhs.value_ == rhs.value_;
}
};
template <class T>
PrintWrap<T> printWrap(const T& value) {
return PrintWrap<T>(value);
}
template <class T>
void print(const PrintWrap<T>& printWrap, std::ostream& os) {
os << "My special print: " << printWrap.value_ << std::endl;
}
template <class T>
bool checkEqualTo(const T& lhs, const T& rhs) {
if (lhs == rhs) return true;
print(lhs, std::cout);
print(rhs, std::cout);
return false;
}
// Google code...
#define CHECK_EQUAL(x,y) checkEqualTo(x,y)
int main() {
std::string value = "Hallo world";
CHECK_EQUAL(printWrap(value), printWrap(value));
return 0;
}
修改强>
您还可以查看此guide,这是GTest关于打印自定义的文档,其中涉及将PrintTo定义在与所讨论的类型相同的命名空间中,以便使用ADL(Argument Dependent Lookup)。 / p>
以下是为此目的使用ADL的一个例子,这是他们设想的扩展机制,它会接缝:
#include <iostream>
#include <cassert>
// Google version template <class T>
void print(const T& value, std::ostream& os) {
os << "Google print: " << value << std::endl;
}
namespace custom {
template <class T>
struct Printable : T
{
template <class...Args>
Printable(Args&&... args)
: T(std::forward<Args>(args)...)
{ }
};
template <class T>
void print(const Printable<T>& value, std::ostream& os) {
os << "My special print: " << value << std::endl;
}
} //custom
int main() {
custom::Printable<std::string> x = "my string";
custom::Printable<std::string> y = "my other string";
assert(! (x == y));
//found by ADL
print(x, std::cout);
return 0;
}
在上面,与参数相同的命名空间中的函数声明具有查找优先级,因此不存在歧义。您不需要使用Printable(可能有更好的完整实现)。您可以根据需要为每种类型打印。
请注意,上面的代码是我的示例。 GTest要求重载为:
void PrintTo(const Bar& bar, ::std::ostream* os)...
此外,您可以重载运算符&lt;&lt;对于您的类型,如文档中所述。