如何根据C++中的标签运行特定函数?



我正在编写一个将运行数百个测试的测试框架。 这些测试中的每一个都是作为独立的函数编写的。 目前,我让我的主函数逐个运行这些测试中的每一个。 我想做的是一个使用标签的系统。 例如,我希望能够运行带有"WiFi"标签的所有测试或运行所有带有"通知"标签的测试。

我尝试查找如何执行此操作,但我所能找到的只是谈论标签调度的文章,这对我没有帮助。 也许标签不是我在这里需要的?

不确定这是否重要,但我在 Mac 上用 c++11 编写,并且我使用的是 VS Code。

顺便说一句,我是堆栈溢出的新手,如果我搞砸了什么,很抱歉。 提前感谢!

编辑: 我会为每个函数使用多个标签。例如,有一个函数需要"WiFi"和"网络"标签,另一个函数需要"触觉"、"通知"和"网络"标签。

你的研究进展不佳的原因是,"标签"是一个非常宽泛的通用术语,并不能真正描述你在做什么。

从根本上说,你试图将两条数据映射在一起;就是这样。不管其中一个片段(你的"标签"(是整数、枚举成员、字符串、类实例还是其他任何东西。

你说过"我需要为每个标签绘制一张新地图">,但我不同意。您只需要一个从"标签"到函数的多重映射(最坏的情况是,如果你也需要反向查找,还需要从函数到"标记"的另一个多重映射(。这些都是微不足道的。

enum class Tag
{
WiFi,
Haptic,
Network,
Notification
};
using Function = std::function<void()>;  // or whatever it is
std::multimap<Tag, Function> tagLookup;
void BindTag(const Tag tag, Function func)
{
tagLookup.emplace(tag, std::move(func));  // I'm using move out of habit
}
void RunFuncsForTag(const Tag tag)
{
auto [start, end] = tagLookup.equal_range(tag);
for (auto it = start; it != end; ++it)
{
const Function& func = it->second;
func();
}
}
int main()
{
BindTag(...);
BindTag(...);
RunFuncsForTag(tag);
}

诚然,如果你不想要很多std::function的副本,还有一些工作要做(你可以将它们存储在另一个容器中,并有一些其他映射来对存储一次的每个函数进行查找(,但这里的基本数据存储原理相当简单。

你可以使用multimap,但你也可以保持简单,只有一个容器和所有的测试:

#include <vector>
#include <type_traits>
template <class E> auto as_underlying(E e) -> std::underlying_type_t<E>
{ return static_cast<std::underlying_type_t<E>>(e); }
enum class Tag : unsigned {
WiFi = 0x01u,
Network = 0x02u,
Haptic = 0x04u,
Notification = 0x08u,
};
auto operator|(Tag lhs, Tag rhs) -> Tag
{
return Tag{as_underlying(lhs) | as_underlying(rhs)};
}
struct Test
{
using F = bool();
Tag tag;
F* test; // or std::function
bool has_tag(Tag tag_to_check) const
{
return as_underlying(tag) & as_underlying(tag_to_check);
}
bool operator()() const { return test(); }
};
template <class Cont>
auto run_by_tag(const Cont& tests, Tag tag)
{
for (const auto& test : tests)
{
if (test.has_tag(tag))
{
test();
}
}
}
auto test()
{
std::vector<Test> tests{
Test{Tag::WiFi | Tag::Network, [] { return true;}},
Test{Tag::Haptic | Tag::Notification | Tag::Network, [] { return false; }},
Test{Tag::Notification, [] { return true;}}
};
run_by_tag(tests, Tag::WiFi);
run_by_tag(tests, Tag::Notification);
}

最新更新