C++ GTest PrintTo使用模板重载
我有一些JSON序列化函数,我想在使用google测试库的单元测试中使用这些函数进行漂亮的打印C++ GTest PrintTo使用模板重载,c++,googletest,C++,Googletest,我有一些JSON序列化函数,我想在使用google测试库的单元测试中使用这些函数进行漂亮的打印 namespace utils { std::string ToJson(app::Foo v){return "foo";}; std::string ToJson(app::Bar v){return "bar";}; } 如果我将PrintTo直接重载到这些类型,它将正常工作 namespace app { void PrintTo(const Foo& v, ::std::ost
namespace utils
{
std::string ToJson(app::Foo v){return "foo";};
std::string ToJson(app::Bar v){return "bar";};
}
如果我将PrintTo直接重载到这些类型,它将正常工作
namespace app
{
void PrintTo(const Foo& v, ::std::ostream* os) {return (*os) << utils::ToJson(v); }
void PrintTo(const Bar& v, ::std::ostream* os) {return (*os) << utils::ToJson(v); }
}
命名空间应用程序
{
void PrintTo(const Foo&v,::std::ostream*os){return(*os)是测试代码的.cpp
文件中或单独的头文件中自定义PrintTo
(模板)函数的声明?如果是前者,则在重载解析点(在GTEST源文件内部)有可能您的自定义重载蓝图不可见,它将返回到template void PrintTo(const T&value,::std::ostream*os){…}gtest printers.h的
。由于您的自定义重载它是一个函数模板,它可能没有为任何模板参数集实例化,因此测试的TU中不存在任何定义……如果是这样,您可以尝试:a)将函数模板声明移动到单独的头,或B)(仅用于尝试我的理论)在您的测试翻译单元中,使用例如Bar
显式实例化PrintTo
函数模板,并查看Foo
和Bar
之间的JSON打印输出之间的行为是否不同(通过适当的GTEST EXPECT/ASSERT failures)@dfri谢谢你的建议,他们帮我找到了trait用法中的bug(必须是is_json_convertable::value,而不是is_json_convertable::type)导致坏模板被忽略现在我有一个模棱两可的调用错误我以为编译器会更喜欢参数模板app::Foo中的模板,但它失败了,出现了一个模棱两可的错误正如您自己解决的那样,GTEST不提供模棱两可的运算符作为自定义PrintTo
(模板)的声明函数在测试代码的.cpp
文件中,或在单独的头文件中?如果是前者,则在重载解析点(在GTEST源文件内部),您的自定义重载蓝图可能不可见,它将返回到模板void PrintTo(const T&value,::std::ostream*os){…}gtest printers.h的
。由于您的自定义重载它是一个函数模板,它可能没有为任何模板参数集实例化,因此测试的TU中不存在任何定义……如果是这样,您可以尝试:a)将函数模板声明移动到单独的头,或B)(仅用于尝试我的理论)在您的测试翻译单元中,使用例如Bar
显式实例化PrintTo
函数模板,并查看Foo
和Bar
之间的JSON打印输出之间的行为是否不同(通过适当的GTEST EXPECT/ASSERT failures)@dfri谢谢你的建议,他们帮我找到了trait用法中的bug(必须是is_json_convertable::value,而不是is_json_convertable::type)导致错误模板被忽略现在我有一个模棱两可的调用错误我以为编译器会更喜欢参数模板app::Foo中的模板,但是它失败了,出现了一个模棱两可的错误因为您已经自己解决了,GTEST没有提供模棱两可的操作符
template <class, class = std::void_t<>>
struct is_json_convertible : std::false_type
{};
template <class T>
struct is_json_convertible<
T, std::void_t<decltype(utils::ToJson(std::declval<T>()))>>
: std::true_type
{};
namespace app
{
template <class T, class = std::enable_if_t<is_json_convertible<T>::value>>
void PrintTo(const T& v, ::std::ostream* os)
{
*os << utils::ToJson(v);
}
}
namespace app
{
template <class T,
class = std::enable_if_t<is_json_convertible<T>::value>>
std::ostream& operator<<(std::ostream& os, const T& v)
{
os << utils::ToJson(v);
return os;
}
}