通过我自己的实现从库中覆盖模板方法

Override templated method from library with my own implementation

本文关键字:覆盖 模板方法 实现 我自己 自己的      更新时间:2023-10-16

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;对于您的类型,如其文档中所述。