[英]Default parameter for partial specialization
我想在用戶端實現什么語法:
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
類型的lvalue,但是您的模板需要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>
,則還將使用默認參數,但將不起作用。
您需要更改擁有比較運算符的結構,以便可以專門化外部模板,請參見: 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>()(...);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.