具有大量選項的過載解析度

如果你需要在幾個選項之間進行選擇,只需通過 enable_if<> 啟用一個選項可能非常繁瑣,因為有幾個條件也需要被否定。

可以使用繼承(即標籤分派)來選擇過載之間的順序。

我們不是測試需要格式良好的東西,也測試所有其他版本條件的否定,而是測試我們需要的東西,最好是在尾隨回報中的 decltype
這可能會留下很好的選擇,我們區分那些使用’標籤’,類似於迭代器 - 特徵標籤(random_access_tag 等)。這是有效的,因為直接匹配比基類更好,這比基類的基類更好。

#include <algorithm>
#include <iterator>

namespace detail
{
    // this gives us infinite types, that inherit from each other
    template<std::size_t N>
    struct pick : pick<N-1> {};
    template<>
    struct pick<0> {};

    // the overload we want to be preferred have a higher N in pick<N>
    // this is the first helper template function
    template<typename T>
    auto stable_sort(T& t, pick<2>)
        -> decltype( t.stable_sort(), void() )
    {
        // if the container have a member stable_sort, use that
        t.stable_sort();
    }

    // this helper will be second best match
    template<typename T>
    auto stable_sort(T& t, pick<1>)
        -> decltype( t.sort(), void() )
    {
        // if the container have a member sort, but no member stable_sort
        // it's customary that the sort member is stable
        t.sort();
    }

    // this helper will be picked last
    template<typename T>
    auto stable_sort(T& t, pick<0>)
        -> decltype( std::stable_sort(std::begin(t), std::end(t)), void() )
    {
        // the container have neither a member sort, nor member stable_sort
        std::stable_sort(std::begin(t), std::end(t));
    }

}

// this is the function the user calls. it will dispatch the call
// to the correct implementation with the help of 'tags'.
template<typename T>
void stable_sort(T& t)
{
    // use an N that is higher that any used above.
    // this will pick the highest overload that is well formed.
    detail::stable_sort(t, detail::pick<10>{});
}

還有其他常用於區分過載的方法,例如精確匹配優於轉換,優於省略號。

但是,tag-dispatch 可以擴充套件到任意數量的選擇,並且意圖更加清晰。