转换为类型擦除的元组

时间:2016-03-14 08:21:34

标签: c++ c++14 signals-slots

在编写信号/插槽系统时,我实例化了模板函数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。有没有办法摆脱这种情况?

1 个答案:

答案 0 :(得分:1)

我看到以下选项:

  1. 延迟将数据移动到类型擦除结构中。
  2. 将对调用者的调用移动到类型擦除结构中,例如通过将调用者实例作为参数传递(当然,这只有在调用者只有一个(或至少很少知名的实例)时才有效。
  3. 如果类型A的数量足够小并且在构造类型擦除结构时已知,则可能会实现一些转换为A,如果它不匹配则抛出。不好,但也不是未定义的行为。
  4. 不是对元组进行类型擦除,而是对单个元组元素进行类型擦除,将它们存储在向量中并对它们调用f。当然这意味着你必须能够在你的擦除类型上调用f,但如果不同f的数量很小,这可能更容易实现。