有符号/无符号特征编程

signed/unsigned trait programming

提问人:xaviersjs 提问时间:11/20/2013 更新时间:11/20/2013 访问量:783

问:

我开始学习 c++ 中的特征和模板。我想知道的是是否可以为有符号/无符号整型创建模板。这个想法是,普通类将(可能)为分离的整数类型实现,而对于无符号整数类型则实现变体。我试过了:

template <typename T>
class FXP<T>
{ ... };

template <typename T>
class FXP<unsigned T>
{ ... };

但这并不能编译。

我什至遇到:

std::is_integral

std::is_signed
std::is_unsigned

那么,我如何将它们付诸实践,以定义一个仅支持这两个变体的类呢?

C++ 模板 C++11 类型特征

评论


答:

5赞 dyp 11/20/2013 #1

使用附加模板参数:

#include <iostream>
#include <type_traits>

template <typename T, class X = void>
struct FXP
{
    // possibly disallow using this primary template:
    // static_assert(not std::is_same<X, X>{},
    //               "Error: type neither signed nor unsigned");
    void print() { std::cout << "non-specialized\n"; }
};

template <typename T>
struct FXP< T, typename std::enable_if<std::is_signed<T>{}>::type >
{  void print() { std::cout << "signed\n"; }  };

template <typename T>
struct FXP< T, typename std::enable_if<std::is_unsigned<T>{}>::type >
{  void print() { std::cout << "unsigned\n"; }  };

struct foo {};

int main()
{
    FXP<foo>().print();
    FXP<int>().print();
    FXP<unsigned int>().print();
}

评论

0赞 dyp 11/20/2013
顺便说一句,这是一个更通用的变体,支持两个以上的选项。
8赞 user3010322 11/20/2013 #2

在这种情况下,有几种方法可以解决这个问题,但我最喜欢的是,在变体数量有限的情况下(例如,一两个布尔值表示它应该以哪种方式运行),模板的部分特殊化通常是最好的方法:

// Original implementation with default boolean for the variation type
template <typename T, bool is_unsigned = std::is_unsigned<T>::value>
class FXP {
     // default implementation here
};

然后,您的下一步是提供部分专用化,该专用化采用类型名称 T,但仅适用于模板参数的特定变体(例如 或 )。truefalse

template <typename T>
class FXP<T, false> {
     // partial specialization when is_unsigned becomes false
};

template <typename T>
class FXP<T, true> {
     // partial specialization when is_unsigned becomes true
};

在这种情况下,如果您编写默认实现,则只需对非默认情况(如真实情况)进行特殊化。

下面是一个示例,其中默认大小写被专用模板参数覆盖: http://coliru.stacked-crooked.com/a/bc761b7b44b0d452

请注意,这仅适用于较小的情况。如果你需要复杂的测试,最好使用 std::enable_if 和一些更复杂的模板参数(如 DyP 的答案)。

祝你好运!