我有一个模板类,只能为标量类型(整数,浮点数等)实例化,我希望成员typedef始终是该类型的带符号变体。那就是:
unsigned int
- > signed int
signed long long
- > signed long long
(已签名)
unsigned char
- > signed char
float
- > float
long double
- > long double
等...
不幸的是,std::make_signed
仅适用于整数类型,而不适用于浮点类型。最简单的方法是什么?我正在寻找using SignedT = ...;
形式的东西,成为我的模板化类的一部分,模板参数T已经保证是标量。
答案 0 :(得分:10)
一个简单的模板别名可以:
#include <type_traits>
template<typename T>
struct identity { using type = T; };
template<typename T>
using try_make_signed =
typename std::conditional<
std::is_integral<T>::value,
std::make_signed<T>,
identity<T>
>::type;
这就是你如何测试它:
int main()
{
static_assert(::is_same<
try_make_signed<unsigned int>::type, int
>::value, "!");
static_assert(std::is_same<
try_make_signed<double>::type, double
>::value, "!");
}
这是live example。
答案 1 :(得分:3)
在我最初尝试使用std::conditional
后,我决定使用SFINAE。我正在使用std::enable_if
来条件化启用浮点类型的特化:
template<typename T, typename Enable = void>
struct my_make_signed {
typedef typename std::make_signed<T>::type type;
};
template<typename T>
struct my_make_signed<T,
typename std::enable_if<std::is_floating_point<T>::value>::type> {
typedef T type;
};
答案 2 :(得分:2)
@jrok最初有代码可以工作,他只需要做一个小调整。这是工作代码:
template<typename T>
struct YourClass
{
using SignedT =
typename std::conditional
<
std::is_floating_point<T>::value, //if floating point type
std::common_type<T>, //use it as-is
std::make_signed<T> //otherwise make sure it is signed
>::type::type; //notice the double ::type
};
如果需要多次使用此功能,则上述结构也可以修改为类型特征类。但是,@ Andy Prowl的答案是使用别名模板,这样更好。
答案 3 :(得分:0)
namespace mine {
template<typename T, bool b>
struct make_signed__ {
typedef T type;
};
template<typename T>
struct make_signed__<T,false> {
typedef typename std::make_signed<T>::type type;
};
template<typename T>
struct make_signed {
typedef typename make_signed__<T, std::is_floating_point<T>::value>::type type;
};
}
int main () {
std::cout << std::is_same<mine::make_signed<unsigned int>::type, int>::value;
std::cout << std::is_same<mine::make_signed<long double>::type, long double>::value;
}