c++ - 在 C++ 中存储视图类型的引用变体
问题描述
我有一个环境,我没有 C++17(C++14 ATM)功能也没有提升。
目前我有一个类负责在我们的域中的服务之间发送消息,这个类使用多种类型的寻址(两种类型都很重要),其中一种可以转换为另一种(假设 A 可以转换为 B)。负责发送消息的类,包含多个(模板化,因为消息没有基类)方法,使用函数重载为两种寻址类型重复。
class Sender{
public:
// old API
template<typename TReq>
send(const A&target, TReq req){send(target, make_request{req});}
// old API
template<typename TReq>
send(const B&target, TReq req){sendB(target, make_request{req});}
protected:
// done for mocking/testing purpose only
virtual send(const A&target, MessageProxy message);
virtual sendB(const A&target, MessageProxy message);
};
寻址 A 和 B 可由用户互换完成(他们不在乎这是 A 还是 B 类型的地址)为了与 google mock 玩得很好,我需要为重载方法提供不同的名称(我可以在 mock 中做到这一点,但决定在这里以不同的方式称呼它们,没有区别)
我要解决的问题很简单。提供单个虚拟发送方法,它将采用对地址类型 A 或 B 的引用的“联合”(将其视为变体<A&,B&>),其使用方式与这些方法的模板版本相同,例如。
virtual send(const TargetProxy &target, MessageProxy message);
可以使用的
EXPECT_CALL(mock, send(Eq(A{}), Message{}))...
EXPECT_CALL(mock, send(Eq(B{}), OtherMessage{}))...
携带 A& 或 B& (TargetProxy) 的类型应该持有对 A OR 到 B 的 const 引用,并且应该只用于将 A 或 B 从模板发送传递到虚拟发送,但我没有找到一个简单的解决方案
解决方案
缺少很多样板,但 PoC 可能是这样的:
#include <utility>
#include <cassert>
#include <iostream>
struct A {};
struct B {};
struct EitherRef : private std::pair<A*, B*>
{
EitherRef(A& a)
: std::pair<A*, B*>(std::addressof(a), nullptr){};
EitherRef(B& b)
: std::pair<A*, B*>(nullptr, std::addressof(b)){};
bool hasA() const {return this->first!=nullptr;}
bool hasB() const {return this->second;}
operator A&() { assert (this->first);return *this->first; }
operator B&() { assert (this->second);return *this->second; }
};
template <typename Func>
void applyVisitor(EitherRef e, Func f)
{
if (e.hasA()) {
f(static_cast<A&>(e));
} else if (e.hasB()) {
f(static_cast<B&>(e));
}
}
void f(const EitherRef& r)
{
struct {
void operator()(A&) {
std::cout <<"A\n";
}
void operator()(B&) {
std::cout <<"B\n";
}
} v;
applyVisitor(r, v);
}
int main(int, char*[])
{
A a1;
B b1;
EitherRef ra{a1};
EitherRef rb{b1};
f(ra);
f(rb);
return 0;
}
推荐阅读
- java - springbatch excel第二次不起作用
- java - libgdx 在地图上设置敌人/怪物的位置不在相机视图中
- docker - OpenMapTiles 泊坞窗不以以前的配置开始
- google-apps-script - 正确的日期未反映在表单提交上
- python-3.x - Beautiful Soup 使用 Python 3 抓取多个 URL
- basic-authentication - Spring Webflux:删除 WWW-authenticate 标头
- git - 如何在 github api 中获取克隆数
- javascript - getElementsByClassName 不工作,而 ID 工作。为什么?
- excel - Proc Export to Excel - 一张表格上的多个表格到一个 xlsx 文件
- ibm-doors - 用于删除门中的传入和传出链接