Understanding Alias Templates

后端 未结 2 1613
礼貌的吻别
礼貌的吻别 2021-01-19 13:00

I asked a question that has several references to the code:

template 
using void_t = void;

I believe I have a generally

2条回答
  •  囚心锁ツ
    2021-01-19 13:14

    In Barry's example from your linked question:

    template
    struct has_to_string
    : std::false_type { };
    
    template
    struct has_to_string()))>
        > 
    : std::true_type { };
    

    void_t is just used to translate the type deduced by decltype to void so that it matches the default argument to the primary template definition. The SFINAE is all taken care of by the decltype expression. You could just as easily do the following:

    //use , void() instead of wrapping in void_t
    //this uses the comma operator to check the type of the to_string call, then change the type to void
    decltype(std::to_string(std::declval()), void())
    

    The former version is much easier to read and void_t doesn't require decltype to work.

    If void_t is available in your implementation you don't need to redefine it. When it's standardised it will be available just like any of the other alias templates in the standard.

    Think about it this way: if T is int, which has a valid std::to_string overload, deduction will look like this:

    has_to_string -> has_to_string because of the default argument. So lets look for specializations of has_to_string with those arguments.

    template
    struct has_to_string()))>
        > 
    : std::true_type { };
    

    Okay, that is a partial specialization for some T and some dependent type. Let's work out that type:

    void_t()))>
    //std::to_string(int&&) is valid and returns a std::string
    void_t
    //void_t changes types to void
    void
    

    Now our specialization looks like this:

    template<>
    struct has_to_string
    : std::true_type { };
    

    This matches our instantiation of has_string, so has_to_string inherits from std::true_type.

    Now think about it when T is struct Foo{};. Again, let's work out that dependent type:

    void_t()))>
    //wait, std::to_string(Foo&&) doesn't exist
    //discard that specialization
    

    With that specialization discarded, we fall back to the primary template:

    template
    struct has_to_string
    : std::false_type { };
    

    So has_to_string inherits from std::false_type.

提交回复
热议问题