字符串转换
String conversions
doctest 需要能够将断言和日志表达式中使用的类型转换为字符串(用于日志记录和报告目的)。 大多数内置类型都是开箱即用的,但您可以通过三种方式告诉 doctest 如何将您自己的类型(或其他第三方类型)转换为字符串。
对于字符串化枚举,请查看此问题。
operator<< overload for std::ostream
这是在 C++ 中提供字符串转换的标准方法 - 您可能已经出于自己的目的提供了这种方法。如果您不熟悉这个习惯用法,它涉及编写以下形式的自由函数:
std::ostream& operator<< (std::ostream& os, const T& value) {
os << convertMyTypeToString(value);
return os;
}
(其中“T”是您的类型,convertMyTypeToString是您编写使您的类型可打印所需的任何代码的地方 - 它不必位于另一个函数中)。
您应该将此函数放在与您的类型相同的命名空间中。
或者,您可能更喜欢将其编写为成员函数:
std::ostream& T::operator<<(std::ostream& os) const {
os << convertMyTypeToString(*this);
return os;
}
doctest::toString overload
如果您不想提供 operator<<``` 重载,或者您想出于测试目的以不同方式转换类型,则可以为您的类型提供 toString()``` 重载它返回doctest::String。
namespace user {
struct udt {};
doctest::String toString(const udt& value) {
return convertMyTypeToString(value);
}
}
请注意,该函数必须与您的类型位于同一命名空间中。如果该类型不在任何命名空间中 - 那么重载也应该在全局命名空间中。 convertMyTypeToString 是您编写使您的类型可打印所需的任何代码的地方。
doctest::StringMaker<T> specialisation
在某些情况下,重载“toString”不能按预期工作。专门化 StringMaker<T> 可以为您提供更精确和可靠的控制 - 但代价是稍微多一些代码和复杂性:
namespace doctest {
template<> struct StringMaker<T> {
static String convert(const T& value) {
return convertMyTypeToString(value);
}
};
}
Translating exceptions
默认情况下,所有从“std::exception”派生的异常都将通过调用“what()”方法(也是 C 字符串)转换为字符串。对于不是从 std::exception 派生的异常类型 - 或者如果 what() 没有返回合
适的字符串 - 使用 REGISTER_EXCEPTION_TRANSLATOR。这定义了一个函数,它接受异常类型并返回“doctest::String”。它可以出现在代码中的任何位置 - 它不必位于同一个翻译单元中。例如:
REGISTER_EXCEPTION_TRANSLATOR(MyType& ex) {
return doctest::String(ex.message());
}
请注意,可以在没有引用的情况下接受异常,但这在 C++ 中被认为是不好的做法。
注册异常转换器的另一种方法是在执行任何测试之前在某些函数中执行以下操作:
// adding a lambda - the signature required is `doctest::String(exception_type)`
doctest::registerExceptionTranslator<int>([](int in){ return doctest::toString(in); });
注册异常翻译器的顺序是可以控制的 - 只需按照所需的顺序调用显式函数,或者在单个翻译单元中以从上到下的方式用宏列出异常翻译器 - 在 doctest 中自动注册的所有内容都可以工作单个翻译单元(源文件)的自上而下的方式。
您还可以覆盖翻译机制,以获取源自``std::exception```的异常。
- 查看 example,它展示了如何对
std::vector 进行字符串化<T>和其他类型/异常。 - 请注意,当专门化
StringMaker<T>或重载toString()时,使用类型String- 它是字符串类型 doctest 使用。std::string不是一个选项,因为 doctest 必须包含<string>标头。 - 为了支持
operator<<(std::ostream&...字符串化,库必须提供std::ostream的前向声明,这就是库所做的 - 但是它目前在所有经过测试的编译器上都有效,但如果 用户希望 100% 符合标准,那么DOCTEST_CONFIG_USE_STD_HEADERS标识符可用于强制包含<iosfwd>默认情况下不包 含标头的原因是,在 MSVC 上(例如)它会拖拽一大堆内容 - 并且在该标头之后。预处理器完成后,翻译单元已增长到 42k 行 C++ 代码 - 而 Clang 和 libc++ 实现得非常好,包括<iosfwd>导致了 400 行代码。