繁体   English   中英

在类模板方法中使用 enable_if 检查两个函数参数是否都是 std::array 或都是 std::vector

[英]Using enable_if, in class template method, to check if two function arguments arguments are both std::array or both std::vector

我不是专业的编码员,如果我的问题显得幼稚或格式错误,我深表歉意。

我试图让一个类成员函数在参数中使用std::arraystd::vector 具体来说,我传递了两个参数,它们要么都是std::array要么都是std::vector

在尝试进行上述工作之前,我所拥有的最小设置仅适用于std::vector参数。 最小设置如下,其中vp是我希望作为向量或数组传递的那些:

// original version

class my_class_A{
// stuf
};

class my_class_B{
// other stuf
};

class I_am_a_class_of_methods{
public:
  inline void my_method(const std::vector<my_class_A> &v,
                        const std::vector<std::array<uint64_t,2> > &p,
                        const my_class_B &x,
                        my_class_B &y){
    // `v` and `p` are used to modify `x` and store the result in `y`
    return;
  }; 
};

我知道我可以用函数重载做我想做的事,但是,我决定用templatesstd::enable_if来达到预期的结果,迫使我更多地了解它们。 好吧,我确实学到了很多我不知道的东西……但还不够。 我基本上尝试过设置特征is_both_array_or_vector ,并且std::enable_if将检查模板调用是否与特征匹配。 我尝试的最后一件事是以下内容,它确实可以编译,但它仅适用于std::vector

// current version

class my_class_A{
// stuf
};

class my_class_B{
// other stuf
};

// set up a type trait to check if both are vector or both are array
template <typename T1, typename T2>                                                                                                                                                                         
struct is_both_array_or_vector{                                                                                                                                                                             
  enum { value = false };                                                                                                                                                                                   
};                                                                                                                                                                                                          

template <typename T1, typename T2, typename A1, typename A2 >                                                                                                                                              
struct is_both_array_or_vector<std::vector<T1, A1>, std::vector<T2, A2> > {                                                                                                                                 
  enum { value = true };                                                                                                                                                                                    
};                                                                                                                                                                                                          

template <typename T1, typename T2, size_t D>                                                                                                                                                               
struct is_both_array_or_vector<std::array<T1, D>, std::array<T2, D> > {                                                                                                                                     
  enum { value = true };                                                                                                                                                                                    
}; 

// conditionally compile with enable_if
class I_am_a_class_of_methods{
public:
  template<template<typename,typename> U, template<typename,typename> S,
           typename Au, typename As> 
  typename std::enable_if<is_both_array_or_vector<U<my_class_A, Au>, S<std::array<uint64_t,2>,As> >::value >::type
  my_method(const U<my_class_A, Au> &v,
            const S<std::array<uint64_t,2>, As> &p,
            const my_class_B &x,
            my_class_B &y){
    // `v` and `p` are used to modify `x` and store the result in `y`
    return;
  }; 
};

当我使用来自 main 的std::vector调用编译时,一切正常。 这(当然)不能用std::array调用编译(编译器当然会抱怨)。

如果我能让模板参数AsAu能够被解释为size_t ,那么模板将找到与std::array调用的匹配项。 然而,这不可能接缝,因为我可以拥有typenamesize_t ,据我所知,不能同时拥有。 因此我的问题是,在这种情况下我如何让 enable_if 工作?

更新:正如 Javier 所说,您可以保留一个私有函数模板来处理一般情况,并为您想要的类型重载两个方法并将它们传递给该模板。

class I_am_a_class_of_methods {
private:
  template <typename C1, typename C2>
  void my_method_priv(const C1& v, const C2& p, const my_class_B& x, my_class_B& y) {
    // ...
  }

 public:
  void my_method(const std::vector<my_class_A>& v,
                 const std::vector<array<uint64_t, 2>>& p,
                 const my_class_B& x,
                 my_class_B& y)
  { my_method_priv(v, p, x, y); }

  template <size_t N1, size_t N2>
  void my_method(const std::array<my_class_A, N1>& v,
                 const std::array<std::array<uint64_t, 2>, N2>& p,
                 const my_class_B& x,
                 my_class_B& y)
  { my_method_priv(v, p, x, y); }
};

我强烈建议在这里使用函数重载作为最佳解决方案。 然而,你说你想尝试和学习。 既然如此,请允许我展示一种与此类似的方法。

请注意,这有点复杂,因为您需要显式模板参数,但检测中并没有涉及更多的元编程,它至少让您了解如何在明智的情况下处理这样的事情 -但在这种情况下,只需使用函数重载。

class I_am_a_class_of_methods
{
    template <typename FirstT, typename SecondT>
    struct Enable { };
    template <typename A1, typename A2>
    struct Enable<std::vector<my_class_A, A1>,
                  std::vector<std::array<uint64_t,2>, A2>>
    {
        using type = void;
    };
    template <std::size_t N1, std::size_t N2>
    struct Enable<std::array<my_class_A, N1>,
                  std::array<std::array<uint64_t,2>, N2>>
    {
        using type = void;
    };

public:
    template <typename T1, typename T2>
    typename Enable<std::decay_t<T1>, std::decay_t<T2>>::type
    my_method(T1 const &v, T2 const &p, my_class_B const &x, my_class_B &y)
    {
        // whatever
    }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM