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;
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
You cannot make this work: Template arguments cannot be values of type
double(they can be an lvalue of typedouble, but your template requires the address of adouble, so that’s off).You can use function templates to make your syntax work
Alternatively, you can use class templates if you are up for some ugly hacks
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. If you only provide<float>, the default argument will be used too, but will not work.