【问题标题】:Why would a template class have an unused type?为什么模板类会有一个未使用的类型?
【发布时间】:2015-02-26 20:17:29
【问题描述】:

我正在查看 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
};

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

typedef unit<pressure_dimension,si::system>      pressure;

在这种情况下,“启用”的作用是什么?

【问题讨论】:

  • 可能是某种 SFINAE?
  • @black 像Enable 这样的名字我也猜到了。
  • 使用enable_if 获得 SFINAE 杠杆作用。见example

标签: c++ templates generic-programming template-classes boost-units


【解决方案1】:

那个类模板是forward declared in "units_fwd.hpp"

template<class Dim,class System, class Enable=void> class unit;

我们看到第三个参数默认为void。我什至会尝试使用 template&lt;class Dim,class System, class=void&gt; class unit; 并在实现中保持无名,但可能存在编译器兼容性或代码标准,这意味着他们将其命名为 Enable

这种“额外”类型允许对前两种类型进行 SFINAE 测试。如果您创建一个特化,其中第三种类型仅对DimSystem 的某些子集有效,则额外参数(默认为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 {};

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

在这种情况下,我们最好只做is_int&lt; int, void &gt;:std::true_type{},但在更复杂的情况下(比如is_integral),我们可以做一个几乎任意的编译时检查,并使用它来启用或禁用true_type 专业化。

【讨论】:

    猜你喜欢
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 2016-02-17
    • 1970-01-01
    • 2017-02-03
    • 1970-01-01
    • 2021-02-06
    • 1970-01-01
    相关资源
    最近更新 更多