访问序列元素的通用方法 P>编写C数组、C++库和C++标准库?< /P>的通用代码的最佳方法是什么?

访问序列元素的通用方法 P>编写C数组、C++库和C++标准库?< /P>的通用代码的最佳方法是什么?,c++,generics,multidimensional-array,C++,Generics,Multidimensional Array,示例:点积 template<class Vector1, class Vector2> constexpr auto dot_product(Vector1 const& v1, Vector2 const& v2) { // doesn't work for Vectors that do not implement () subscripting using return_type = decltype(v1(0) + v2(0)); return

示例:点积

template<class Vector1, class Vector2>
constexpr auto dot_product(Vector1 const& v1, Vector2 const& v2) {
  // doesn't work for Vectors that do not implement () subscripting
  using return_type = decltype(v1(0) + v2(0)); 
  return_type tmp = return_type{};
  // doesn't work for e.g. std::tuple
  for (std::size_t i = 0, e = size(v1); i != e; ++i) {
    tmp += v1(i) * v2(i);
  }
  return tmp;
}
模板
constexpr自动点积(矢量1常量和v1,矢量2常量和v2){
//不适用于未实现()下标的向量
使用return_type=decltype(v1(0)+v2(0));
return_type tmp=return_type{};
//不适用于例如std::tuple
对于(std::size\u t i=0,e=size(v1);i!=e;++i){
tmp+=v1(i)*v2(i);
}
返回tmp;
}
  • 访问元素时出现问题:

    • 对于C数组
      数组[i]
      ,C矩阵
      数组[i][j]
    • C++ >代码> STD::向量< /代码>,代码>矢量[i] < /Calp>
    • <> LI>对于C++ +>代码>元组,<代码> STD::GET(元组)< /C> < /LI> 对于一个C++线性代数向量/矩阵(如本征):<代码>向量(I)< /COD>,<代码>矩阵(I,J)< /COD>
  • 迭代有一个问题:

    • C数组循环的运行时,
      std::vectors
    • boost::fusion
      用于例如
      std::array
      std::tuple
    • 线性代数库的自定义表达式,可在封面下处理这两种情况(例如,Eigen使用表达式模板)
  • Geometry使用
    get
    函数来解决访问问题,这会导致到处都是
    get
    s的卷积代码。它还使用策略来调度不同的迭代方法


有更好的替代方案吗?

您可以使用基于策略的模板

template <typename T> 
struct DefaultUsePolicy {
    int DoSomethingWithT( T const & ) {
        return 42;
    }
};
template < typename T, typename UsePolicy = DefaultUsePolicy<T>>
int Generic( T& arg ) {
    UsePolicy use;
    return use.DoSomethingWithT(arg);
}
模板
结构DefaultUsePolicy{
int dosomethingWith(T const&){
返回42;
}
};
模板
int通用(T&arg){
使用政策使用;
返回use.DoSomethingWithT(arg);
}
然后为公共类型提供一些默认实现,如果用户有自定义类型,则让用户编写一个策略

通用功能将在其所需的策略中记录服务需求


它类似于使用
std::unique\u ptr
std::default\u deleter
来提供对销毁所拥有指针的控制。

您可以将
get
函数包装在类中,类似于:

#define Return(ret) decltype ret { return ret; }

template <typename T>
class Getter
{
private:
    T& t;
public:
    constexpr explicit Getter(T&t) : t(t) {}

    constexpr auto operator () (std::size_t i) const
    -> Return((get(t, i)))

    constexpr auto operator () (std::size_t i, std::size_t j) const
    -> Return((get(t, i, j)))

    operator T&() const { return t; }
};

template <typename T>
Getter<T> make_getter(T&t) { return Getter<T>(t); }
#定义返回(ret)decltype ret{Return ret;}
模板
类吸气剂
{
私人:
T&T;
公众:
constexpr显式Getter(T&T):T(T){
constexpr自动运算符()(std::size\u t i)const
->返回((get(t,i)))
constexpr自动运算符()(std::size\u t i,std::size\u t j)const
->返回((get(t,i,j)))
运算符T&()常量{return T;}
};
模板
Getter make_Getter(T&T){return Getter(T);}
然后

template<class Vector1, class Vector2>
constexpr auto dot_product(Vector1 const& v1_arg, Vector2 const& v2_arg) {
  auto v1 = make_getter(v1_arg);
  auto v2 = make_getter(v2_arg);
  using return_type = decltype(v1(0) + v2(0)); 
  return_type tmp = return_type{};
  for (std::size_t i = 0, e = size(v1); i != e; ++i) {
      tmp += v1(i) * v2(i);
  }
  return tmp;
}
模板
constexpr自动点积(矢量1常量和v1常量、矢量2常量和v2常量){
auto v1=制造吸气剂(v1_arg);
自动v2=生成getter(v2\u arg);
使用return_type=decltype(v1(0)+v2(0));
return_type tmp=return_type{};
对于(std::size\u t i=0,e=size(v1);i!=e;++i){
tmp+=v1(i)*v2(i);
}
返回tmp;
}

Generic access您是在谈论索引
operator[]()
重载吗?@πάνταῥεῖ 不一定,但大部分是肯定的。你所说的
(即[i,j]是允许的,但[i][j]不是)是什么意思。这是不正确的。@对于用户定义的类型很简单。我强调了这一点,并在数组访问之前添加了运算符,以使其更加清晰。@gnzlbg您不能使
[I,j]
对用户定义的类型有效。这是逗号运算符。