微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

局部专业化的默认参数

如何解决局部专业化的默认参数

| 我想在用户端实现什么语法:
double a(1.),b(2.),deps(.1);
bool res1 = compare<double>()(a,b);        // works with default eps
bool res2 = compare<double,&deps>()(a,b);  // works with explicitly provided eps
float c(1.),d(1.). feps(.1);
bool res3 = compare<float>()(c,d);  // don\'t have default eps - must not compile
bool res4 = compare<float,&feps>()(c,d);   // works only with provided eps
我现在有什么实现方式(由于不允许部分专业化的认参数,因此无法正常工作):
extern double eps_double; // somewhere defined and initialized

template<typename T,const T* eps>
struct compare { // actually inherits std::binary_function
  bool operator()(const T& t1,const T& t2) {
    return t1 < t2 - *eps;
  }
};
template<const double* eps = &eps_double>
struct compare<double,eps> { // the same as in default implementation
};
我尝试使用具有静态成员的enable_if和wrapper类,但是不能将静态成员分配给extern变量; 更新: 实际的问题是通用结构和专用结构的名称相等。我不知道如何重命名它:
// treats all explicitly passed eps and don\'t need default parameter
template<typename T,const T* eps>
struct compare_eps { // need another name! 
  bool operator()(const T& t1,const T& t2) {
    return t1 < t2 - *eps;
  }
};
// don\'t need default parameter either
// because we always kNow what eps to use for a concrete type
template<typename T>
struct compare { 
  // define nothing -> will not compile on types we don\'t have specialization for
}; 
template<>
struct compare<double> { 
  // use here eps_double hardcoded
}; 
    

解决方法

我不知道你为什么认为这有意义
compare<double,deps>
您无法做到这一点:模板参数不能是
double
类型的值(它们可以是
double
类型的左值,但是您的模板需要
double
的地址,因此\处于关闭状态)。 您可以使用功能模板来使语法正常工作
extern double eps_double;

template<typename T>
types::compare<T,&eps_double> compare(
  typename enable_if<is_same<T,double>>::type * = 0
) {
  return types::compare<T,&eps_double>(); 
}

template<typename T,const T *eps>
types::compare<T,eps> compare() {
  return types::compare<T,eps>(); 
}
另外,如果您打算接受一些丑陋的技巧,则可以使用类模板
template<typename T,const T* eps = &eps_double>
struct compare { 
  bool operator()(const T& t1,const T& t2) {
    return t1 < t2 - *eps;
  }
};
如果您同时提供两个参数,则将不使用默认参数。如果仅提供“ 9”,则将使用默认参数并将其起作用。如果仅提供
<float>
,则也将使用默认参数,但将不起作用。     ,您需要更改拥有比较运算符的结构,以便可以专门化外部模板,请参见:http://ideone.com/xqtjz 代码是:
extern double eps_double; // somewhere defined and initialized
extern double deps;  // NOTE: you have to make these extern a well,else cannot work
extern float feps;

template<typename T>
struct compare {
  // this internal structure now has the operator()
  template <const T* eps>
  struct it
  {
    bool operator()(const T& t1,const T& t2) const {
      return t1 < t2 - *eps;
    }
  };
};

// specialize compare for double
template<>
struct compare<double>
{
  // here you can provide the default
  template<const double* eps=&eps_double>
  struct it
  {
    bool operator()(const double& t1,const double& t2)
    {
      return t1 < t2 - *eps;
    }
  };
};

int main(void)
{
  double a(1.),b(2.);
  bool res1 = compare<double>::it<>()(a,b);        // works with default eps
  bool res2 = compare<double>::it<&deps>()(a,b);   // works with explicitly provided eps
  float c(1.),d(1.);
  bool res3 = compare<float>::it<>()(c,d);  // don\'t have default eps - will not compile
  bool res4 = compare<float>::it<&feps>()(c,d);   // works only with provided eps
}
    ,我会采用类似特征的方法:
template<class T>
struct DefaultEps;

template<>
struct DefaultEps<double>
{
  static const double eps = 4.0;
};

// may or may not be needed in .cpp
// const double DefaultEps<double>::eps;

template<>
struct DefaultEps<float>
{
  static const float eps = 4.0;
};

// may or may not be needed in .cpp
// const float DefaultEps<float>::eps;

template<class T,class E = DefaultEps<T> >
struct Compare
{
  bool operator()(T const &t1,T const &t2)
  {
    return(t1 < t2 - E::eps);
  }
};
然后在需要特定的epsilon时:
struct SpecificEps
{
  static const float eps = 4.0;
};

// may or may not be needed in .cpp
// const float SpecificEps::eps;
并使用它:
Compare<float,SpecificEps>()(...);
    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。