1

ユーザー側で実現したい構文:

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クラスとラッパークラスを試しましたが、静的メンバーを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
}; 
4

3 に答える 3

2

なぜこれが理にかなっていると思うのか分かりません

compare<double, deps>

これを機能させることはできません。テンプレート引数を型の値にすることはできませんdouble(型の左辺値にすることはできますdoubleが、テンプレートにはaのアドレスが必要な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;
  }
};

両方の引数を指定した場合、デフォルトの引数は使用されません。のみ<double>を指定すると、デフォルトの引数が使用され、機能します。を指定するだけの場合<float>、デフォルトの引数も使用されますが、機能しません。

于 2011-04-14T11:33:39.437 に答える
1

外部テンプレートを特殊化できるように、比較演算子を所有する構造を変更する必要があります。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
}
于 2011-04-14T11:32:09.370 に答える
0

私は特性のようなアプローチで行きます:

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);
  }
};

そして、特定のイプシロンが必要な場合:

struct SpecificEps
{
  static const float eps = 4.0;
};

// may or may not be needed in .cpp
// const float SpecificEps::eps;

そしてそれを使用します:

Compare<float, SpecificEps>()(...);
于 2011-04-14T14:47:36.183 に答える