代码之家  ›  专栏  ›  技术社区  ›  0xbadf00d

我的部分模板专用化的模板参数不可推断

  •  0
  • 0xbadf00d  · 技术社区  · 9 年前

    请考虑以下代码段:

    template<class E>
    class vector_expression {};
    
    template<class Tuple>
    class vector
        : public vector_expression<vector<Tuple>>
    {
    public:
        using value_type = typename Tuple::value_type;
    };
    
    template<typename T>
    using dynamic_vector = vector<std::vector<T>>;
    
    namespace detail
    {
        template<class E>
        constexpr bool is_vector_expression_v = std::is_base_of_v<vector_expression<std::decay_t<E>>, std::decay_t<E>>;
    
        template<class E>
        struct value_type { using type = std::decay_t<E>; };
        template<class E>
        struct value_type<vector_expression<std::decay_t<E>>> { using type = typename std::decay_t<E>::value_type; };
        template<class E>
        using value_type_t = typename value_type<E>::type;
    }
    
    
    int main()
    {
        static_assert(std::is_same<detail::value_type_t<dynamic_vector<double>>, double>::value, "not the same");   
        return 0;
    }
    

    我想要 value_type_t<E> 成为 value_type 在中指定 E 无论何时 E 是一个 vector_expression 。上面的代码不起作用,因为模板参数 E 是不可推论的 值_类型 .如何使代码工作?

    DEMO

    2 回复  |  直到 9 年前
        1
  •  2
  •   Jarod42    9 年前

    std::decay_t<E> 事实上无法推断 std::decay<E>::type (事实上 E 在您的特定情况下可能导致相同类型)。

    需要第二次修复才能通过 static_assert :

    dynamic_vector<double> 不是 vector_expression 但是从它继承,你的专业性不匹配。您可以使用SFINAE解决以下问题:

    template<class E, typename Enabler = void>
    struct value_type { using type = std::decay_t<E>; };
    
    template<class E>
    struct value_type<E, std::enable_if_t<is_vector_expression_v<E>>> {
        using type = typename std::decay_t<typename E::type>::value_type;
    };
    

    Demo

        2
  •  1
  •   Barry    9 年前

    第一个问题是你的部分专业化是不可演绎的。这是一个更容易的解决方案,你可以放下 std::decay_t :

    template<class E>
    struct value_type<vector_expression<E>> { using type = typename E::value_type; };
    

    然而,现在你有一个更大的问题,那就是它不能做你想做的事情。 dynamic_vector<double> 不是 vector_expression<E> 对于任何 E 继承 从…起 vector_expression<vector<std::vector<T>>> ,但这对本次比赛的目的没有帮助。因此,上面的修复程序将编译,但您仍然会匹配主模板-这会给您带来错误 value_type .

    你可能想要的是专注于 值_类型 作为typedef。即:

    template <class... > using void_t = void;
    template <class T> struct tag_t { using type = T; }; // courtesy of Yakk
    
    template<class E, class=void>
    struct value_type : tag_t<std::decay_t<E>> { };
    
    template<class E>
    struct value_type<E, void_t<typename std::decay_t<E>::value_type>> 
    : tag_t<typename std::decay_t<E>::value_type> { };
    

    现在你的 static_assert 通过。