所以我试图验证std::tuple
的所有元素是否满足某个条件。我目前的解决方案使用C ++ 17倍epxressions:
template <typename F, typename Tuple, size_t...Is>
_CR_INLINE bool tuple_all_of(F&& fn, Tuple&& t, std::index_sequence<Is...>) {
return (std::forward<F>(fn)(std::get<Is>(std::forward<Tuple>(t))) && ...);
}
template <typename F, typename Tuple>
_CR_INLINE bool tuple_all_of(F&& fn, Tuple&& t) {
return tuple_all_of(std::forward<F>(fn), std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>());
}
它在最新的clang和gcc中编译,但在MSVC中失败,因为折叠表达式尚未实现。 (https://blogs.msdn.microsoft.com/vcblog/2017/05/10/c17-features-in-vs-2017-3/)
那么有没有使用折叠表达式的类似解决方案?
这是应该如何使用的:
template<typename...Components, typename Callable>
void FindComponents(Callable&& fn) {
for (auto& node : m_Entities) {
auto tp = std::make_tuple(node.GetComponent<Components>()...);
if (!tuple_all_of([](auto& p) { return p != nullptr; }, tp))
continue;
apply_from_tuple(fn, tp);
}
}
所以,只有当一个节点附加了所请求的组件时(即fn
!= nullptr),我才会调用GetComponent
。也许有更好的解决方案?
答案 0 :(得分:2)
根据Visual C++ Language Conformance支持表达式从VS2017 15.5开始支持/std:c++17
(或/std:c++latest
)编译器选项。
答案 1 :(得分:0)
您可以使用std::apply
更轻松地解压缩元组:
template <typename F, typename Tuple>
constexpr bool tuple_all_of(F&& fn, const Tuple& t)
{
return std::apply([&fn](const auto&... xs)
{
return (fn(xs) && ...);
}, t);
}
折叠表达式可以替换为for_each_argument
:
template <typename F, typename Tuple>
constexpr bool tuple_all_of(F&& fn, const Tuple& t)
{
bool result = true;
std::apply([&](const auto&... xs)
{
for_each_argument([&](const auto& x)
{
if(fn(x)) result = false;
}, xs...);
}, t);
return result;
}
template <class F, class... Ts>
void for_each_argument(F f, Ts&&... a)
{
(void)std::initializer_list<int>{(f(std::forward<Ts>(a)), 0)...};
}
答案 2 :(得分:0)
我想你可以使用未使用的C风格数组初始化的旧技巧[警告:代码未经过测试]
template <typename F, typename Tuple, size_t...Is>
_CR_INLINE bool tuple_all_of(F&& fn, Tuple&& t, std::index_sequence<Is...>) {
using unused=bool[];
bool ret { true };
(void)unused { true, (ret = ret && std::forward<F>(fn)(std::get<Is>(std::forward<Tuple>(t)))) ... };
return ret;
}