为什么模板类有未使用的类型?

Ray*_*des 4 c++ templates generic-programming boost-units template-classes

我正在审查boost单元库,我很困惑为什么boost :: units :: unit类有一个额外的模板参数.这是一个例子:

http://www.boost.org/doc/libs/1_57_0/boost/units/unit.hpp

template<class Dim,class System, class Enable>
class unit
{
    public:
        typedef unit<Dim, System>   unit_type;
        typedef unit<Dim,System>    this_type;
        typedef Dim                 dimension_type; 
        typedef System              system_type;

        unit() { }
        unit(const this_type&) { }
        //~unit() { }  

        this_type& operator=(const this_type&) { return *this; }

        // sun will ignore errors resulting from templates
        // instantiated in the return type of a function.
        // Make sure that we get an error anyway by putting.
        // the check in the destructor.
        #ifdef __SUNPRO_CC
        ~unit() {
            BOOST_MPL_ASSERT((detail::check_system<System, Dim>));
            BOOST_MPL_ASSERT((is_dimension_list<Dim>));
        }
        #else
    private:
        BOOST_MPL_ASSERT((detail::check_system<System, Dim>));
        BOOST_MPL_ASSERT((is_dimension_list<Dim>));
        #endif
};
Run Code Online (Sandbox Code Playgroud)

该类用于向维度系统添加维度.

typedef unit<pressure_dimension,si::system>      pressure;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,"启用"服务的目的是什么?

Yak*_*ont 5

该类模板是向前声明的"units_fwd.hpp".

template<class Dim,class System, class Enable=void> class unit;
Run Code Online (Sandbox Code Playgroud)

在那里我们看到第3个参数默认为void.我甚至会想做,template<class Dim,class System, class=void> class unit;并且在实现中也没有名字,但是可能存在编译器兼容性或代码标准,这意味着它们给它起了名字Enable.

这种"额外"类型允许对前两种类型进行SFINAE测试.如果您创建一个专门化,其中第三种类型仅对某些子集有效,Dim并且System额外参数(默认为void)允许您这样做.

你甚至可以把你的基本实现空(无论是;{};具有不同的效果),只有专注,使失败的试验被视为无效选项参数.

这是SFINAE的玩具示例:

template<class T, class=void> struct is_int : std::false_type {};
template<class T> struct is_int< T,
  std::enable_if_t< std::is_same<T, int>{} >
> : std::true_type {};
Run Code Online (Sandbox Code Playgroud)

基础专业化继承自false_type.但是,如果类型T在下一个特化中通过了我的测试,则首选,结果继承自true_type.

在这种情况下,我们只需要做得更好is_int< int, void >:std::true_type{},但在更复杂的情况下(比如说is_integral),我们可以进行几乎任意的编译时检查并使用它来启用或禁用特化true_type.