Currying for templates in C++ metaprogramming

前端 未结 2 678
深忆病人
深忆病人 2021-02-20 05:58

This is more of a conceptual question. I\'m trying to find the easiest way of converting a two-arg template (the arguments being types) into a one-arg template. I.e., binding on

2条回答
  •  遇见更好的自我
    2021-02-20 06:20

    I think the typical way of doing this is keep everything in the world of types. Don't take template templates - they're messy. Let's write a metafunction named ApplyAnInt that will take a "metafunction class" and apply int to it:

    template 
    struct ApplyAnInt {
        using type = typename Func::template apply;
    };
    

    Where a simple metafunction class might be just checking if the given type is an int:

    struct IsInt {
        template 
        using apply = std::is_same;
    };
    
    static_assert(ApplyAnInt::type::value, "");
    

    Now the goal is to support:

    static_assert(ApplyAnInt>::type::value, "");
    

    We can do that. We're going to call types that contain _ "lambda expressions", and write a metafunction called lambda which will either forward a metafunction class that isn't a lambda expression, or produce a new metafunction if it is:

    template 
    struct lambda {
        using type = T;
    };
    
    template 
    struct lambda::value>>
    {
        struct type {
            template 
            using apply = typename apply_lambda::type;
        };
    };
    
    template 
    using lambda_t = typename lambda::type;
    

    So we update our original metafunction:

    template 
    struct ApplyAnInt
    {
        using type = typename lambda_t::template apply;
    };
    

    Now that leaves two things: we need is_lambda_expr and apply_lambda. Those actually aren't so bad at all. For the former, we'll see if it's an instantiation of a class template in which one of the types is _:

    template 
    struct is_lambda_expr : std::false_type { };
    
    template