samedi 15 juillet 2017

Tag Dispatch, why is wrong overload called?

In the code below the assertion does not fail, so how can type_supports_deref_t<T>{}) construct anything else besides 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;
}

Has the output:

No-ptr  .. 
true

Which in my mind only makes sense if the false_type overload is called, but the assertion does not fail, so what is going on?

Aucun commentaire:

Enregistrer un commentaire