简体   繁体   English

模板类专业化与函数重载

[英]Template class specialization vs function overloading

The title is not the best so let me explain: I'm experimenting with a custom mini-stl (for learning purposes) and currently implementing the std::distance function. 标题不是最好的,所以让我解释一下:我正在试验一个自定义的mini-stl(出于学习目的),当前正在实现std::distance函数。 The function must behave differently for random access iterators and simple input iterators. 对于随机访问迭代器和简单输入迭代器,该函数的行为必须有所不同。

Function overloading 函数重载

Both std (in Microsoft's implementation) and EASTL use operator overloading to select the appropriate function, something like this: std(在Microsoft的实现中)和EASTL都使用运算符重载来选择适当的函数,如下所示:

namespace internal
{
    template <typename Iter>
    inline typename IteratorTraits<Iter>::DifferenceType DistanceImpl(Iter first, Iter last, InputIteratorTag)
    {
        // ...
    }

    template <typename Iter>
    inline typename IteratorTraits<Iter>::DifferenceType DistanceImpl(Iter first, Iter last, RandomAccessIteratorTag)
    {
        // ...
    }
}

template <typename Iter>
inline typename IteratorTraits<Iter>::DifferenceType Distance(Iter first, Iter last)
{
    // the last parameter of the function selects the proper DistanceImpl
    return internal::DistanceImpl<Iter>(first, last, (typename IteratorTraits<Iter>::IteratorCategory)());
}

I guess the temporary object (the category tag parameter which is an empty struct) will be optimized away since it's not used. 我猜临时对象(类别标记参数是一个空结构)将被优化掉,因为它没有被使用。

Class specialization with static function 具有静态功能的类专门化

What's about the specialization of a helper class with a static function? 带有静态函数的辅助类的专业化如何?

namespace internal
{
    template <typename Cat>
    struct DistanceImpl;

    template <>
    struct DistanceImpl<InputIteratorTag>
    {
        template <typename Iter>
        inline static typename IteratorTraits<Iter>::DifferenceType Calc(Iter first, Iter last)
        {
            // ...
        }
    };

    template <>
    struct DistanceImpl<RandomAccessIteratorTag>
    {
        template <typename Iter>
        inline static typename IteratorTraits<Iter>::DifferenceType Calc(Iter first, Iter last)
        {
            // ...
        }
    };
}

template <typename Iter>
inline typename IteratorTraits<Iter>::DifferenceType Distance(Iter first, Iter last)
{
    return internal::DistanceImpl<typename IteratorTraits<Iter>::IteratorCategory>::Calc<Iter>(first, last);
}

Questions 问题

  • Difference(s) between the two solution? 两种解决方案之间的差异? (Including performance and reliability) (包括性能和可靠性)
  • Advantages/Disadvantages? 优点缺点?

Tag dispatch automatically handles inheritance hierarchies; 标记分派可自动处理继承层次结构; explicit specializations don't. 明确的专业则没有。 This is particularly important with iterators, because the standard iterator category tags form an inheritance hierarchy: random_access_iterator_tag derives from bidirectional_iterator_tag which derives from forward_iterator_tag which derives from input_iterator_tag . 这是迭代器尤为重要,因为迭代器分类标签形成一个继承层次: random_access_iterator_tag派生自bidirectional_iterator_tag从派生forward_iterator_tag从派生input_iterator_tag

The first version works out of the box when given a forward or bidirectional iterator by selecting the input iterator overload. 通过选择输入迭代器重载为它提供前向或双向迭代器时,第一个版本即开即用。 The second doesn't and requires additional specializations or some other changes. 第二个不需要,并且需要其他专业化或其他一些更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM