Tag Dispatch,为什么称为错误的重载?

时间:2017-07-15 14:25:02

标签: c++ c++11 templates typetraits

在下面的代码中,断言没有失败,那么除了type_supports_deref_t<T>{})之外true_type如何构建其他任何内容?

#include <iostream>
#include <memory>
#include <type_traits>
#include <utility>
#include <typeinfo>

template <typename T>
struct ptr_traits {
    using supports_deref = std::false_type;
};

template <typename T>
struct ptr_traits<T*> {
    using supports_deref = std::true_type;
};

template <typename T>
struct ptr_traits<std::unique_ptr<T>> {
    using supports_deref = std::true_type;
};

template <typename T>
struct ptr_traits<std::shared_ptr<T>> {
    using supports_deref = std::true_type;
};

template <typename T>
using type_supports_deref_t = typename ptr_traits<typename std::remove_cv<T>::type>::supports_deref;


template <typename T>
T& foo_impl(T&& t, std::false_type){
    std::cout<<"No-ptr  .. \n";
    return t;
}

template <typename T>
T& foo_impl(T&& t, std::true_type){
    std::cout<<"Ptr .. \n";
    return *t;
}

template <typename T>
T& foo(T&& t){
    return foo_impl(t, type_supports_deref_t<T>{}); 
}

struct Bar {
    int value = 10;
};


int main(){
    Bar* b1 = new Bar();
    foo(b1); // calls no ptr...
    std::cout<<std::boolalpha;
    std::cout<<(type_supports_deref_t<Bar*>::value); // returns true
    static_assert(std::is_same<std::true_type, decltype(type_supports_deref_t<Bar*>{})>::value, ""); // passes
    return 0;
}

有输出:

No-ptr  .. 
true

在我看来,只有在调用false_type重载时才有意义,但断言没有失败,那么发生了什么?

编辑:这是一个可能感兴趣的人的工作版本,它有点难看......

template <typename T>
struct ptr_traits {
    using supports_deref = std::false_type;
};

template <typename T>
struct ptr_traits<T*> {
    using supports_deref = std::true_type;
};

template <typename T>
struct ptr_traits<std::unique_ptr<T>> {
    using supports_deref = std::true_type;
};

template <typename T>
struct ptr_traits<std::shared_ptr<T>> {
    using supports_deref = std::true_type;
};

template <typename T>
using type_supports_deref_t = typename ptr_traits<typename std::remove_reference<typename std::remove_cv<T>::type>::type>::supports_deref;


template <typename T>
T& foo_impl(T&& t, std::false_type){
    std::cout<<"No-ptr  .. \n";
    return t;
}

template <typename T>
auto foo_impl(T&& t, std::true_type) -> decltype(*t){
    std::cout<<"Ptr .. \n";
    return *t;
}

template <typename T>
auto foo(T&& t) -> decltype(foo_impl(t, type_supports_deref_t<T>{})){
    return foo_impl(t, type_supports_deref_t<T>{}); 
}

0 个答案:

没有答案