c++ - 基于在其参数上调用流输出运算符的能力重载函数
问题描述
我有一个通用函数,它接受两个参数,比较它们,如果它们不相等则打印一条消息。现在,我只有这个相对愚蠢的功能:
template <typename T>
static void AreEqual(const T& expected,
const T& actual,
const std::string& message = "") {
if (!(actual == expected)) {
std::cout << message;
}
}
多年来,这已经充分发挥了作用。它最常与原语一起调用,但也用于比较较大的用户定义的结构/类。
我想通过提供一个重载来扩展函数,当它们不匹配时打印预期值和实际值,但不会破坏定义operator==
但不定义的类的函数operator<<
。我的想法是创建一个使用 SFINAE 来禁用重载的重载(如果operator<<
丢失)。到目前为止,我已经想出了这个:
template <
typename T,
typename = typename std::enable_if_t<
std::is_same_v<decltype(std::cout << *((T*)nullptr)), decltype(std::cout)>>>
static void AreEqual(const T& expected,
const T& actual,
const std::string& message = "") {
if (!(actual == expected)) {
std::cout << "Expected " << expected << ", got " << actual << ". " << message;
}
}
这可以编译,但它没有被选择为T
or int
,std::string
我不知道为什么。我的第一个怀疑是我的论点is_same_v
不知何故格式不正确,但如果是这种情况,我不知道如何或如何弄清楚如何解决它。
问题1:这一切是否必要?我可以在没有模板元编程的情况下获得相同的结果吗(最好在坚持使用 C++11 时)
问题 2:如果这是最好的方法,我如何有效地调试我的模板?
解决方案
您可能会执行以下操作:
struct overload_low_priority {};
struct overload_high_priority : overload_low_priority {};
template <typename T>
static auto AreEqualImpl(const T& expected,
const T& actual,
const std::string& message,
overload_high_priority)
-> decltype(std::cout << expected, void()) // SFINAE
{
if (!(actual == expected)) {
std::cout << "Expected " << expected << ", got " << actual << ". " << message;
}
}
template <typename T>
static void AreEqualImpl(const T& expected,
const T& actual,
const std::string& message,
overload_low_priority) // Fallback
{
if (!(actual == expected)) {
std::cout << message;
}
}
template <typename T>
static void AreEqual(const T& expected,
const T& actual,
const std::string& message = "")
{
AreEqualImpl(expected, actual, message, overload_high_priority{});
}
推荐阅读
- c# - 通过 TContextService 和 TContextImplementation 对 AddDbContextCheck 进行健康检查
- sql-server - 将表传递给存储过程会出现无效列错误
- visual-studio - 为 Tizen 安装 Visual Studio 工具时出错
- r - geom_line() 用不同的线型连接特定的组变量
- docker - Gitlab 的工件 zip 文件为空
- node.js - 使用 pkg 将带有 native-node-printer 的 Node.js 项目打包成可执行文件
- mongodb - 使用golang从mongo获取一段json字符串
- android - 如何使用计费取消应用内测试购买:2.0.3 库
- algorithm - 了解 Freeverb 的梳状滤波器实现
- azure-data-lake - 如何提取包含多个 CSV 数据集的 ZIP 文件