如何正确删除模板函数中的代码重复
How correctly to remove code repetition in template function
我有这样的代码("spaceship"-like 运算符)。
template <class T>
int comparator(const T &a, const T &b){
if (a < b){
return -1;
}else if (a > b){
return +1;
}
return 0;
}
inline int comparator(const char *a, const char *b){
return strcmp(a, b); // I never tried this, included just to get the idea
}
inline int comparator(char const a, char const b){
return a - b;
}
inline int comparator(int const a, int const b){
return a - b;
}
我如何轻松删除多个有符号类型(char、short、int、long 等)的重复项。我尝试使用 SFINAE,但结果不是很令人鼓舞。
首先将模板函数委托给模板 class
template <class T>
int comparator(const T &a, const T &b){
return comparator_impl<T>::comparator(a, b);
}
默认模板class实现是你已经写的:
template<class T>
class comparator_impl {
public:
static int comparator(const T &a, const T &b){
if (a < b){
return -1;
}else if (a > b){
return +1;
}
return 0;
};
现在,有一个单独的模板 class 将用于有符号整数类型:
template<class T>
class signed_int_comparator_impl {
public:
static int comparator(T a, T b)
{
return a-b;
}
return 0;
};
现在,特化第一个模板 class,继承第二个模板的特化:
template<>
class comparator_impl<char> : public signed_int_comparator_impl<char> {};
template<>
class comparator_impl<int> : public signed_int_comparator_impl<int> {};
对剩余的有符号整数类型进行泡沫、冲洗、重复。
如果您想 comparator_impl
专攻 const char *
,请随意。
- 对于模板专业化,建议使用模板 class/struct,而不是模板函数。参见 http://www.gotw.ca/publications/mill17.htm
std::is_integral
together with std::is_signed
look like the correct tool for your SFINAE. Here is a working example: https://ideone.com/8wm54h
您可以混合使用重载、标记调度和模板,如下例所示:
#include<type_traits>
#include<utility>
#include<iostream>
template <class T>
int comparator_(char, const T &a, const T &b){
std::cout << "catch all" << std::endl;
return (a<b)?-1:((a>b)?1:0);
}
template<typename T>
std::enable_if_t<std::is_same<T,int>::value or std::is_same<T,char>::value, int>
comparator_(int, T const a, T const b){
std::cout << "char or int" << std::endl;
return a - b;
}
template<typename... A>
int comparator(A&&... args) {
return comparator_(0, std::forward<A>(args)...);
}
int main() {
comparator(42,0);
comparator('c', 'g');
comparator(42u, 0u);
}
我有这样的代码("spaceship"-like 运算符)。
template <class T>
int comparator(const T &a, const T &b){
if (a < b){
return -1;
}else if (a > b){
return +1;
}
return 0;
}
inline int comparator(const char *a, const char *b){
return strcmp(a, b); // I never tried this, included just to get the idea
}
inline int comparator(char const a, char const b){
return a - b;
}
inline int comparator(int const a, int const b){
return a - b;
}
我如何轻松删除多个有符号类型(char、short、int、long 等)的重复项。我尝试使用 SFINAE,但结果不是很令人鼓舞。
首先将模板函数委托给模板 class
template <class T>
int comparator(const T &a, const T &b){
return comparator_impl<T>::comparator(a, b);
}
默认模板class实现是你已经写的:
template<class T>
class comparator_impl {
public:
static int comparator(const T &a, const T &b){
if (a < b){
return -1;
}else if (a > b){
return +1;
}
return 0;
};
现在,有一个单独的模板 class 将用于有符号整数类型:
template<class T>
class signed_int_comparator_impl {
public:
static int comparator(T a, T b)
{
return a-b;
}
return 0;
};
现在,特化第一个模板 class,继承第二个模板的特化:
template<>
class comparator_impl<char> : public signed_int_comparator_impl<char> {};
template<>
class comparator_impl<int> : public signed_int_comparator_impl<int> {};
对剩余的有符号整数类型进行泡沫、冲洗、重复。
如果您想 comparator_impl
专攻 const char *
,请随意。
- 对于模板专业化,建议使用模板 class/struct,而不是模板函数。参见 http://www.gotw.ca/publications/mill17.htm
std::is_integral
together withstd::is_signed
look like the correct tool for your SFINAE. Here is a working example: https://ideone.com/8wm54h
您可以混合使用重载、标记调度和模板,如下例所示:
#include<type_traits>
#include<utility>
#include<iostream>
template <class T>
int comparator_(char, const T &a, const T &b){
std::cout << "catch all" << std::endl;
return (a<b)?-1:((a>b)?1:0);
}
template<typename T>
std::enable_if_t<std::is_same<T,int>::value or std::is_same<T,char>::value, int>
comparator_(int, T const a, T const b){
std::cout << "char or int" << std::endl;
return a - b;
}
template<typename... A>
int comparator(A&&... args) {
return comparator_(0, std::forward<A>(args)...);
}
int main() {
comparator(42,0);
comparator('c', 'g');
comparator(42u, 0u);
}