我这里有一些代码,它使用特殊值来检查变量是否已初始化。
#define NULLVALUE_FLOAT -9999
#define NULLVALUE_INT -9999
#define NULLVALUE_UINT 0
#define NULLVALUE_DOUBLE -9999
#define NULLVALUE_LONG -9999
#define NULLVALUE_LONGLONG -9999
#define NULLVALUE_CSTRING ""
bool isNull(float value) { return NULLVALUE_FLOAT == value; }
bool isNull(double value); ...
bool isNull(long value);...
bool isNull(int value);...
bool isNull(UINT value);...
bool isNull(CString value);...
因此无符号的特殊值为零,有符号整数和浮点数为-9999,字符串为空字符串。
现在我想将其重写为一个模板函数,但由于CString版本而出现问题。我能做的最好的是两个函数,一个用于基本类型,一个用于CString。
template<typename T,
bool E = std::is_fundamental<T>::value && !std::is_unsigned<T>::value && (std::is_floating_point<T>::value || std::is_integral<T>::value),
bool E2 = std::is_fundamental<T>::value && std::is_unsigned<T>::value>
bool isNull(const T &t)
{
if (E)
return t == -9999;
else if (E2)
return t == 0;
else
return false;
}
bool isNull(const CString & s)
{
return s == "";
}
是否可以仅使用一个函数实现此功能,即使添加其他具有默认值的类也是如此?
答案 0 :(得分:5)
如果您将注意力从定义函数转移到定义命名Null值的方式,解决方案就会非常容易。
添加一个公开value
成员的特征类。专门那然而你觉得方便。
template<typename T, typename = void>
struct NullValueHolder{};
template<typename T>
constexpr decltype(NullValueHolder<T>::value) NullValue = NullValueHolder<T>::value;
// Utility for easy referral
template<typename T>
struct NullValueHolder<T, std::enable_if_t<std::is_arithmetic<T>::value && std::is_signed<T>::value>> {
static constexpr T value = -9999;
};
template<typename T>
struct NullValueHolder<T, std::enable_if_t<std::is_unsigned<T>::value>> {
static constexpr T value = 0;
};
template<>
struct NullValueHolder<CString, void> {
static constexpr const char * value = "";
};
以上大量使用SFINAE。主模板中的void
必须与专业化匹配才能选择该专业化。如果符合条件,则每个enable_if_t
都会提供void
。
现在该函数自行编写:
template<typename T>
bool isNull(T const& t) { return t == NullValue<T>; }
答案 1 :(得分:0)
现在,C ++ 17已经出现在visual studio中,这可以通过“if constexpr”功能轻松解决。让编译器根据需要生成函数。
android:duplicateParentState="true"