通过我自己的实现从库中覆盖模板方法
Override templated method from library with my own implementation
Google测试声明模板方法PrintTo
:
template <typename T>
void PrintTo(const T& value, ::std::ostream* os);
有几个没有模板的过载。我还为自定义类型添加了过载。
我的问题是我不喜欢Google提供的默认模板方法,而是想这样实现:
template<typename T>
void PrintTo(const T &val, ::std::ostream *os)
{
QString str;
QDebug(&str) << val;
*os << qUtf8Printable(str);
}
这将解决许多QT类型的问题。我无法更改Google测试代码中的实现。我需要用自己的代码重新完成它。
使用我的模板方法,我得到此编译器错误:
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已经支持数千种类型,我不想错过该功能!
问题是编译器无法执行过载,因为您的功能签名与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;
}
编辑
您还可以查看本指南,这是GTEST关于打印自定义的文档,它涉及在与所讨论的类型相同的命名空间中定义printto,以便使用ADL(参数依赖于参数查找)。
以下是将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;
}
在上面,函数声明与参数具有查找优先级相同的命名空间,因此不存在歧义。您无需使用可打印(也许可以更好地实现)。您可以根据需要进行每种类型的打印。
请注意,上面的代码是我的示例。GTEST要求超载为:
void PrintTo(const Bar& bar, ::std::ostream* os)...
此外,您只能超载运算符&lt;&lt;对于您的类型,如其文档中所述。
相关文章:
- 将成员函数指针作为参数传递给模板方法
- 模板方法访问正向声明的类仅在没有此指针的情况下无法编译
- C++11:模板方法的模板函数调用无法编译?
- 如何从ECS中的模板方法获取组件?
- 使用 SFINAE 设计模板方法
- 一个模板方法,用于同时接受常量和非常量参数
- C++模板方法中的循环依赖关系
- 在 C++ 中使用模板方法重写类方法
- 类中的模板方法
- 基于枚举参数调用专用模板方法
- 模板中的模板方法 - 实例声明和类方法声明签名不同
- 确保模拟的 GTest 方法覆盖虚拟方法
- 可变参数模板方法
- 使用模板方法为标头提供空 cpp 时出现问题
- SFINAE 方法在 clang 中完全禁用基类的模板方法
- 将函数和成员函数传递给模板方法
- 从非模板类调用专用模板方法
- 有没有办法仅在两个模板参数相同时才覆盖匹配的模板方法?
- 通过我自己的实现从库中覆盖模板方法
- 为什么C++显式实例化的模板方法不能覆盖虚拟方法?