gpt4 book ai didi

c++ - 检查元组中的项目是否包含特定方法

转载 作者:行者123 更新时间:2023-12-04 14:54:34 25 4
gpt4 key购买 nike

我有一个元组,我正在尝试为元组中的每个对象调用 initialize()。现在,某些对象可能不包含该功能。我知道我可以通过使用 C++20 requires 功能来检查类是否包含给定函数来完成这项工作。不幸的是,我使用的是 MSVC,它尚不支持。

有没有可能用不同的方式来写?我可以使用 C++20,但它应该在 MSVC 上编译

template <class... Args>
struct CustomTuple : std::tuple<Args...> {
// Calls "initialize() for each item inside the tuple if that function exists"
template <std::size_t I = 0>
auto initialize() {
std::decay_t<decltype(std::get<I>(*this))> item;
constexpr bool has_initialize = requires() { // doesnt't work on MSVC
item.initialize();
};
if constexpr (has_initialize) {
std::get<I>(*this).initialize();
}
if constexpr (I + 1 != sizeof...(Args)) {
initialize<I + 1>();
}
}
};

最佳答案

如果您还没有访问 requires 的权限,那么您将不得不使用 SFINAE 并编写一个类型特征来检测 initialize() 是否是一个可调用的成员函数。

这可以通过 std::void_t 来完成, 尽管有点笨拙:

#include <type_traits> // std::void_t
#include <utility> // std::declval

template <typename T, typename = void>
struct has_initialize_impl : std::false_type {};

template <typename T>
struct has_initialize_impl<T,
std::void_t<decltype(std::declval<T&>().initialize())>
> : std::true_type {};

template <typename T>
inline constexpr auto has_initialize = has_initialize_impl<T>::value;

上述特征检查是否有任何可变引用 T& 可以调用名为 initialize() 的函数。如果表达式的格式正确,则 has_initialized 的计算结果为 true;否则,它的计算结果为 false

然后只需稍加改动就可以将其用于您的其余代码:

template <class... Args>
struct CustomTuple : std::tuple<Args...> {
// Calls "initialize() for each item inside the tuple if that function exists"
template <std::size_t I = 0>
auto initialize() {
// Note: no need to construct a temporary/unused 'item' type,
// we can just use 'tuple_element' here to get the type
using element_type = typename std::tuple_element<I, std::tuple<Args...>>::type;

if constexpr (has_initialize<element_type >) {
std::get<I>(*this).initialize();
}
if constexpr (I + 1 != sizeof...(Args)) {
initialize<I + 1>();
}
}
};

Live Example


如果您认为您可能有更多需要检测功能的情况,但仍然没有 C++20 requires 支持,那么可能值得考虑添加“detected"-idiom + boilerplate 到您的代码中,可以在 cppreference 上找到.

这与 std::void_t 的行为相同,但如果经常需要则更方便。这仍然比 c++20 的要求更迟钝,但如果您的编译器不支持它,您就没有太多选择。

使用 is_detected_v,您只需为需要验证的任何表达式定义模板类型别名,然后将其简单地传递给特征即可。

例如,上述解决方案可以简洁地解决为:

template <typename T>
using detect_initialize = decltype(std::declval<T&>().initialize());

...

if constexpr (is_detected_v<detect_initialize, decltype(item)>) {
...
}

Live Example

关于c++ - 检查元组中的项目是否包含特定方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68337380/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com