在编写信号/槽系统时,我实例化了一个模板函数 invoker
:
template <typename F, typename ...A, ::std::size_t ...I>
inline void do_invoke(F const& f, ::std::tuple<A...> const& t,
::std::index_sequence<I...> const)
{
f(::std::get<I>(t)...);
}
template <typename F, typename ...A>
inline void invoker(variant_type const& v, void const* const v)
{
do_invoke<F, A...>(get<F>(v),
*static_cast<::std::tuple<A...> const*>(v),
::std::make_index_sequence<sizeof...(A)>());
}
在这里variant_type
是类型删除对象的任何容器(例如 ::boost::any
,但可以是任何东西)。问题是假设 v
指向 ::std::tuple<A...>
,这可能不是真的,但是元组 v
指向的点可能仍可转换为 ::std::tuple<A...>
.我不知道是什么A...
是了,当我调用invoker()
因为此信息已被删除。因此,我不能这样做:
template <typename ...A, typename ...B, ::std::size_t ...I>
::std::tuple<A...> convert(::std::tuple<B...> const& t,
::std::index_sequence<I...> const)
{
return ::std::tuple<A...>{::std::get<I>(t)...};
}
在打电话之前。如果元组类型不完全匹配,我有 UB。有办法摆脱这种情况吗?
最佳答案
我看到以下选项:
- 延迟将数据移动到类型删除结构中。
- 将对 invoker 的调用移动到类型删除结构中,例如通过将调用程序实例作为参数传递(当然,这仅在只有一个(或至少很少有众所周知的实例)调用程序的情况下才有效。
- 如果
A
类型的数量足够少并且在您构造类型删除结构时已知,您可以对A
执行一些转换,如果它抛出不匹配。不好,但也不是未定义的行为。 - 不是对元组进行类型删除,而是对单个元组元素进行类型删除,将它们存储在 vector 中并在其上调用 f。当然,这意味着您必须能够在删除类型上调用 f,但如果不同 f 的数量很少,这可能更容易完成。
关于c++ - 转换为类型删除的元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35982540/