2

我有一个将给定函数应用于给定函数的函数fstd::tuple t如下所示,如果t大小错误,则会生成编译时错误消息。我想知道是否可以用不同的方式编写它,以便当元组大小错误时,函数调用不会发生(可能使用enable_if或类似的东西)并生成运行时错误消息(而不是编译时错误消息)。

提前致谢。

#include <tuple>
#include <iostream>
#include <functional>

template<int ...> struct seq {};

template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};

template<int ...S> struct gens<0, S...>{ typedef seq<S...> type; };

template <typename R, typename Tp, typename ...FArgs> 
struct t_app_aux {
  template<int ...S>
  R static callFunc(std::function<R (FArgs...)> f,Tp t,seq<S...>) {
    return f(std::get<S>(t) ...);
  }
};

template <typename R, typename Tp, typename ...FArgs>
R t_app(std::function<R (FArgs...)> f, Tp t) {
  static_assert(std::tuple_size<Tp>::value == sizeof...(FArgs), "type error: t_app wrong arity"); //wrong size generates a compile error, how about runtime check?
  return t_app_aux<R, Tp, FArgs...>::callFunc(f,t,typename gens<sizeof...(FArgs)>::type());
}

int main(void)
{
  std::tuple<int, float, double> t = std::make_tuple(1, 1.2, 5);
  std::function<double (int,float,double)> foo = [](int x, float y, double z) {
    return x + y + z;
  };
  std::cout <<  t_app(foo,t) << std::endl;
}

- 更新 -

一点点动机和解释我的想法。这可能在政治上不正确,但是说,我想将输入元组与模板函数内部定义的固定元组进行比较compare_me(比如内部元组是make_tuple(2,3))。如果我可以抑制编译时错误,那么我可以只返回一个falseoncompare_me(make_tuple(1,2,3))compare_me(make_tuple(1,2))and trueon make_tuple(2,3)。更实际地,可以使用相同的技术编写模板eq来比较两个可能不同大小的元组,并false在它们的大小不匹配时返回。

大小不匹配可以视为编译错误。我也同意应该尽早揭露真正的失败。但我想有时人们可能想要宽容或重新考虑什么是真正的失败。这是真的,特别是考虑到有这样的函数std::tuple_cat实际上可以给你的函数一个不同大小的元组。

4

1 回答 1

2

使用enable_if和 您static_assert的条件仅在尺寸匹配时有条件地启用当前功能。创建另一个仅在条件为 false 时才启用的函数,并从该函数中抛出异常。

template <typename R, typename Tp, typename ...FArgs>
auto t_app(std::function<R (FArgs...)> f, Tp t)
    -> typename std::enable_if<std::tuple_size<Tp>::value == sizeof...(FArgs), R>::type {
//  static_assert(std::tuple_size<Tp>::value == sizeof...(FArgs), "type error: t_app wrong arity"); //wrong size generates a compile error, how about runtime check?
  return t_app_aux<R, Tp, FArgs...>::callFunc(f,t,typename gens<sizeof...(FArgs)>::type());
}

template <typename R, typename Tp, typename ...FArgs>
auto t_app(std::function<R (FArgs...)>, Tp)
    -> typename std::enable_if<std::tuple_size<Tp>::value != sizeof...(FArgs), R>::type {
  throw std::runtime_error("type error: t_app wrong arity");
}

现场演示

于 2014-01-22T03:13:18.280 回答