[英]Default parameter for partial specialization
What syntax I want to achieve on user side: 我想在用户端实现什么语法:
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
What implementation for this I have now (not working because default parameters for partial specialization are not allowed): 我现在有什么实现方式(由于不允许部分专业化的默认参数,因此无法正常工作):
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
};
I've tried with enable_if and wrapper classes that have static members, but static members can't be assigned to extern variables; 我尝试使用具有静态成员的enable_if和wrapper类,但是不能将静态成员分配给extern变量;
UPDATE: The actual problem is name equality for general struct and specialized struct. 更新:实际的问题是通用结构和专用结构的名称相等。 I don't know how to make it work without renaming:
我不知道如何重命名它:
// 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
};
I don't know why you think that this make sense 我不知道你为什么认为这有意义
compare<double, deps>
You cannot make this work: Template arguments cannot be values of type double
(they can be an lvalue of type double
, but your template requires the address of a double
, so that's off). 您无法做到这一点:模板参数不能是
double
类型的值(它们可以是double
类型的lvalue,但是您的模板需要double
的地址,因此不可用)。
You can use function templates to make your syntax work 您可以使用功能模板来使语法正常工作
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>();
}
Alternatively, you can use class templates if you are up for some ugly hacks 另外,如果您打算接受一些丑陋的技巧,则可以使用类模板
template<typename T, const T* eps = &eps_double>
struct compare {
bool operator()(const T& t1, const T& t2) {
return t1 < t2 - *eps;
}
};
The default argument will not be used if you provide both arguments. 如果您同时提供两个参数,则将不使用默认参数。 If you provide only
<double>
, the default argument will be used and will work. 如果仅提供
<double>
,则将使用默认参数并将其起作用。 If you only provide <float>
, the default argument will be used too, but will not work. 如果仅提供
<float>
,则还将使用默认参数,但将不起作用。
You need to change the structure which owns the comparison operator such that you can specialize the outer template, see: http://ideone.com/xqtjz 您需要更改拥有比较运算符的结构,以便可以专门化外部模板,请参见: http : //ideone.com/xqtjz
the code is: 代码是:
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
}
I would go with traits-like approach: 我会采用类似特征的方法:
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);
}
};
and then when specific epsilon is needed: 然后在需要特定的epsilon时:
struct SpecificEps
{
static const float eps = 4.0;
};
// may or may not be needed in .cpp
// const float SpecificEps::eps;
and use it: 并使用它:
Compare<float, SpecificEps>()(...);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.