C++ C+;中的多模式varadic模板+;

C++ C+;中的多模式varadic模板+;,c++,templates,c++14,variadic-templates,template-meta-programming,C++,Templates,C++14,Variadic Templates,Template Meta Programming,根据我所读到的,我认为这是不可能的,但是我希望这里的人可能知道一些解决方案,可以让这个工作 我有一门C语言的向量(数学)课++ template <typename T, size_t N> class vec; 哪个是有效的(尚未测试) 然而,我想实现一种模式,如 template <typename F> friend vec<typename std::result_of<F&&(T&&)>::type, N>

根据我所读到的,我认为这是不可能的,但是我希望这里的人可能知道一些解决方案,可以让这个工作

我有一门C语言的向量(数学)课++

template <typename T, size_t N> class vec;
哪个是有效的(尚未测试)

然而,我想实现一种模式,如

template <typename F> friend vec<typename std::result_of<F&&(T&&)>::type, N> apply(F&& f, const vec<T, N>& V);
template <typename F> friend vec<typename std::result_of<F&&(T&&, T&&)>::type, N> apply(F&& f, const vec<T, N>& V1, const vec<T, N>& V2);
template <typename F> friend vec<typename std::result_of<F&&(T&&, T&&)>::type, N> apply(F&& f, const vec<T, N>& V1, const T& V2);
template <typename F> friend vec<typename std::result_of<F&&(T&&, T&&)>::type, N> apply(F&& f, const T& V1, const vec<T, N>& V2);
template <typename F, typename U> friend vec<typename std::result_of<F&&(T&&, U&&)>::type, N> apply(F&& f, const vec<T, N>& V1, const vec<U, N>& V2);
template <typename F, typename U> friend vec<typename std::result_of<F&&(T&&, U&&)>::type, N> apply(F&& f, const vec<T, N>& V1, const U& V2);
template <typename F, typename U> friend vec<typename std::result_of<F&&(U&&, T&&)>::type, N> apply(F&& f, const vec<U, N>& V1, const vec<T, N>& V2);
template <typename F, typename U> friend vec<typename std::result_of<F&&(U&&, T&&)>::type, N> apply(F&& f, const U& V1, const vec<T, N>& V2);
编辑:

根据弗兰克的评论,我正在寻找类似于

template<typename F, typename ...Args, size_t N>
vec<typename std::enable_if<sum<is_vec<Args,N>...>::value > 0, std::result_of<F&&(base_type<Args>::type&&...)>::type>::type, N>
(F&& f, Args&&...args) {
    vec<typename std::result_of<F&&(base_type<Args>::type&&...)>::type, N> result;
    for(std::size_t i = 0 ; i < N ; ++i) { result.v[i] = f(extract_v(std::forward<Args>(args),i)...); }
    return result;
}
模板
向量::类型,N>
(F&&F,Args&&…Args){
vec结果;
对于(std::size_t i=0;i

但是,我不确定这个版本是否可以编译,因为它可能太模糊,无法损害
N

的值。通过部分模板专门化和参数包扩展的组合,您可以实现您想要的

#include <array>

template<typename T, std::size_t N>
using Vec = std::array<T, N>;

template<typename T>
struct extract {
  static auto exec(T const& v, std::size_t) {return v;}
  enum { size = 1 };
};

template<typename T, std::size_t N>
struct extract<Vec<T,N>> {
  static auto exec(Vec<T,N> const& v, std::size_t i) {return v[i];}
  enum {size = N};
};

template<typename T>
auto extract_v(T const& v, std::size_t i) {return extract<T>::exec(v, i);}

template<typename... args>
struct extract_size {
    enum {size = 1};
};

template<typename first, typename... rest>
struct extract_size<first, rest...> {
    enum {
        rest_size_ = extract_size<rest...>::size,
        self_size_ = extract<first>::size,
        size = rest_size_ > self_size_ ? rest_size_ : self_size_ 
    };

    static_assert(self_size_ == 1 || rest_size_ == 1 || rest_size_ == self_size_, "");
};

template<typename F, typename... args_t>
auto apply(F const& cb, args_t&&... args) {
  constexpr std::size_t size = extract_size<std::decay_t<args_t>...>::size;
  using result_t = decltype(cb(extract_v(std::forward<args_t>(args),0)...));

  Vec<result_t, size> result;

  for(std::size_t i = 0 ; i < size ; ++i) {
    result[i] = cb(extract_v(std::forward<args_t>(args),i)...);
  }

  return result;
}
#包括
模板
使用Vec=std::array;
模板
结构提取{
静态自动执行(T const&v,std::size_T){return v;}
枚举{size=1};
};
模板
结构提取{
静态自动执行(Vec const&v,std::size_t i){return v[i];}
枚举{size=N};
};
模板
自动提取_v(T const&v,std::size_ti){return extract::exec(v,i);}
模板
结构提取大小{
枚举{size=1};
};
模板
结构提取大小{
枚举{
剩余大小=提取大小::大小,
自身大小=提取::大小,
大小=剩余大小>自身大小?剩余大小:自身大小
};
静态断言(self_size_==1 | | rest_size_==1 | | rest_size_==self_size_124;,“”;
};
模板
自动应用(F常量和cb、参数和…参数){
constexpr std::size\u t size=extract\u size::size;
使用result_t=decltype(cb(extract_v(std::forward(args),0)…);
Vec结果;
对于(标准::大小\u t i=0;i
不确定您到底想要什么,但

在我看来,从类型列表中提取
Vec
、iff(当且仅当)维度的自定义类型特征非常有用,在类型列表中至少有一个
Vec
,并且没有不同长度的
Vec

我建议如下,主要基于模板专门化

template <std::size_t, typename ...>
struct dimVec;

// ground case for no Vecs: unimplemented for SFINAE failure !
template <>
struct dimVec<0U>;

// ground case with one or more Vecs: size fixed
template <std::size_t N>
struct dimVec<N> : public std::integral_constant<std::size_t, N>
 { };

// first Vec: size detected
template <std::size_t N, typename T, typename ... Ts>
struct dimVec<0U, Vec<T, N>, Ts...> : public dimVec<N, Ts...>
 { };

// another Vec of same size: continue
template <std::size_t N, typename T, typename ... Ts>
struct dimVec<N, Vec<T, N>, Ts...> : public dimVec<N, Ts...>
 { };

// another Vec of different size: unimplemented for SFINAE failure !
template <std::size_t N1, std::size_t N2, typename T, typename ... Ts>
struct dimVec<N1, Vec<T, N2>, Ts...>;

// a not-Vec type: continue
template <std::size_t N, typename T, typename ... Ts>
struct dimVec<N, T, Ts...> : public dimVec<N, Ts...>
 { };
请注意,
N
变量用于启用/禁用函数,但它本身很有用:它用于将
std::index_序列
0
传递到
N-1
到第一个助手函数
applyH1()

它使用一组模板函数
extrV()


如果我读对了(我真的不确定我是否读对了),我想你可以使用好的旧的部分模板专门化来实现这一点?如果这是正确的,那么我会给出一个正确的答案。不完全是这样,我想让任意数量的参数,一个是长度为N的向量,另一个是长度为N的标量或向量,然后使用广播将函数应用于向量的每个元素,请参阅C++/puedsocode的最后一个代码块,该代码大致符合我的要求。我曾考虑过部分专门化,但如何将多个参数传递给函数,可能使用元组和C++17中的std::apply,但我需要一个C++14的解决方案,所以这不会有任何帮助。哦,我想我明白了你的意思,那么,沿着这些基本思路,还有一些东西?(这不是你想要的100%,但我认为它解决了你的主要障碍)是的,接缝大约正确,但是,N应该是通过提取v以确保向量长度相同,另一个问题是,如果第二个参数是向量,而不是第一个参数,那么同样合法,有什么方法可以断言它们中的任何一个是vec类型吗?特别是会产生编译时错误的东西,最好是替换失败,可能类似于
summation\u template::value>=1
我问了一个关于扩展此解决方案以处理矩阵和向量的后续问题,你能帮上忙吗?
#include <array>

template<typename T, std::size_t N>
using Vec = std::array<T, N>;

template<typename T>
struct extract {
  static auto exec(T const& v, std::size_t) {return v;}
  enum { size = 1 };
};

template<typename T, std::size_t N>
struct extract<Vec<T,N>> {
  static auto exec(Vec<T,N> const& v, std::size_t i) {return v[i];}
  enum {size = N};
};

template<typename T>
auto extract_v(T const& v, std::size_t i) {return extract<T>::exec(v, i);}

template<typename... args>
struct extract_size {
    enum {size = 1};
};

template<typename first, typename... rest>
struct extract_size<first, rest...> {
    enum {
        rest_size_ = extract_size<rest...>::size,
        self_size_ = extract<first>::size,
        size = rest_size_ > self_size_ ? rest_size_ : self_size_ 
    };

    static_assert(self_size_ == 1 || rest_size_ == 1 || rest_size_ == self_size_, "");
};

template<typename F, typename... args_t>
auto apply(F const& cb, args_t&&... args) {
  constexpr std::size_t size = extract_size<std::decay_t<args_t>...>::size;
  using result_t = decltype(cb(extract_v(std::forward<args_t>(args),0)...));

  Vec<result_t, size> result;

  for(std::size_t i = 0 ; i < size ; ++i) {
    result[i] = cb(extract_v(std::forward<args_t>(args),i)...);
  }

  return result;
}
template <std::size_t, typename ...>
struct dimVec;

// ground case for no Vecs: unimplemented for SFINAE failure !
template <>
struct dimVec<0U>;

// ground case with one or more Vecs: size fixed
template <std::size_t N>
struct dimVec<N> : public std::integral_constant<std::size_t, N>
 { };

// first Vec: size detected
template <std::size_t N, typename T, typename ... Ts>
struct dimVec<0U, Vec<T, N>, Ts...> : public dimVec<N, Ts...>
 { };

// another Vec of same size: continue
template <std::size_t N, typename T, typename ... Ts>
struct dimVec<N, Vec<T, N>, Ts...> : public dimVec<N, Ts...>
 { };

// another Vec of different size: unimplemented for SFINAE failure !
template <std::size_t N1, std::size_t N2, typename T, typename ... Ts>
struct dimVec<N1, Vec<T, N2>, Ts...>;

// a not-Vec type: continue
template <std::size_t N, typename T, typename ... Ts>
struct dimVec<N, T, Ts...> : public dimVec<N, Ts...>
 { };
template <typename ... Args>
static constexpr auto dimVecV { dimVec<0U, Args...>::value };
template <typename F, typename ... Args, std::size_t N = dimVecV<Args...>>
auto apply (F && f, Args ... as)
 { return applyH1(std::make_index_sequence<N>{}, f, as...); }
template <std::size_t ... Is, typename F, typename ... Args>
auto applyH1 (std::index_sequence<Is...> const &, F && f, Args ... as)
   -> Vec<decltype(applyH2<0U>(f, as...)), sizeof...(Is)>
 { return { applyH2<Is>(f, as...)... }; }
template <std::size_t I, typename F, typename ... Args>
auto applyH2 (F && f, Args ... as)
 { return f(extrV<I>(as)...); }
template <std::size_t I, typename T, std::size_t N>
constexpr auto extrV (Vec<T, N> const & v)
 { return v[I]; }

template <std::size_t I, typename T>
constexpr auto extrV (T const & v)
 { return v; }
#include <array>
#include <iostream>
#include <type_traits>

template <typename T, std::size_t N>
class Vec;

template <std::size_t, typename ...>
struct dimVec;

// ground case for no Vecs: unimplemented for SFINAE failure !
template <>
struct dimVec<0U>;

// ground case with one or more Vecs: size fixed
template <std::size_t N>
struct dimVec<N> : public std::integral_constant<std::size_t, N>
 { };

// first Vec: size detected
template <std::size_t N, typename T, typename ... Ts>
struct dimVec<0U, Vec<T, N>, Ts...> : public dimVec<N, Ts...>
 { };

// another Vec of same size: continue
template <std::size_t N, typename T, typename ... Ts>
struct dimVec<N, Vec<T, N>, Ts...> : public dimVec<N, Ts...>
 { };

// another Vec of different size: unimplemented for SFINAE failure !
template <std::size_t N1, std::size_t N2, typename T, typename ... Ts>
struct dimVec<N1, Vec<T, N2>, Ts...>;

// a not-Vec type: continue
template <std::size_t N, typename T, typename ... Ts>
struct dimVec<N, T, Ts...> : public dimVec<N, Ts...>
 { };

template <typename ... Args>
static constexpr auto dimVecV { dimVec<0U, Args...>::value };

template <std::size_t I, typename T, std::size_t N>
constexpr auto extrV (Vec<T, N> const & v)
 { return v[I]; }

template <std::size_t I, typename T>
constexpr auto extrV (T const & v)
 { return v; }

template <typename T, std::size_t N>
class Vec
 {
   private:
      std::array<T, N> d;

   public:
      template <typename ... Ts>
      Vec (Ts ... ts) : d{{ ts... }}
       { }

      T & operator[] (int i)
       { return d[i]; }

      T const & operator[] (int i) const
       { return d[i]; }
 };


template <std::size_t I, typename F, typename ... Args>
auto applyH2 (F && f, Args ... as)
 { return f(extrV<I>(as)...); }

template <std::size_t ... Is, typename F, typename ... Args>
auto applyH1 (std::index_sequence<Is...> const &, F && f, Args ... as)
   -> Vec<decltype(applyH2<0U>(f, as...)), sizeof...(Is)>
 { return { applyH2<Is>(f, as...)... }; }

template <typename F, typename ... Args, std::size_t N = dimVecV<Args...>>
auto apply (F && f, Args ... as)
 { return applyH1(std::make_index_sequence<N>{}, f, as...); }

long foo (int a, int b)
 { return a + b + 42; }

int main ()
 {
   Vec<int, 3U>  v3;
   Vec<int, 2U>  v2;

   auto r1 { apply(foo, v2, v2) };
   auto r2 { apply(foo, v3, v3) };
   auto r3 { apply(foo, v3, 0)  };

   static_assert( std::is_same<decltype(r1), Vec<long, 2U>>{}, "!" );
   static_assert( std::is_same<decltype(r2), Vec<long, 3U>>{}, "!" );
   static_assert( std::is_same<decltype(r3), Vec<long, 3U>>{}, "!" );

   // apply(foo, v2, v3); // compilation error
   // apply(foo, 1, 2);   // compilation error

 }