代码之家  ›  专栏  ›  技术社区  ›  deets

模板化类型的模板专用化

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

    我对c++模板编程领域很陌生。

    我知道我可以专门设计函数模板,例如在我的例子中 toJson -我想使用ADL的函数模板。

    例如。

    template<typename T>
    Json::Value toJson(const T&);
    

    其中Json::Value由JsonCPP库提供。

    现在,我可以专门为“正常”类型做这个:

    template<>
    Json::Value toJson<MyClass>(const MyClass&)
    

    太棒了

    然而,我有一种类型, KalmanFilter<3, 3, 3, double> (显然,这是完全参数化的),它又有几个特征3矩阵作为类型,谁的维数是根据卡尔曼滤波器中的积分模板参数确定的。我想像这样专门介绍Json:

    template<>
    Json::Value toJson<KalmanFilter<int, int, int, T>>(const KalmanFilter<int, int, int, T> ...)
    

    也许有不同的方法可以实现这一点(例如,Eigen对所有类型的std::ostream操作符进行了泛型重载)。

    或者我必须使用不同声明的toJson,比如

    template<int A, int B, int C, typename FloatT>
    Json::Value toJson(const KalmanFilter<A, B, C, FloatT>&);
    

    ?

    2 回复  |  直到 9 年前
        1
  •  3
  •   Vittorio Romeo    9 年前

    我会使用模板来解决这个问题 struct 而不是专门化函数模板, because of potential drawbacks .

    // Hide implementation details in `impl` namespace.
    namespace impl
    {
        // Forward-declaration of helper converter struct.
        template<typename>
        struct json_converter;
    
        // Example specialization: `int`.
        template<>
        struct json_converter<int>
        {
            Json::Value to_json(const int&) 
            { 
                // <Conversion logic here.>
            }
        };
    
        // Example specialization: `KalmanFilter`.        
        template<int A, int B, int C, typename FloatT>
        struct json_converter<KalmanFilter<A, B, C, FloatT>>
        {
            Json::Value to_json(const KalmanFilter<A, B, C, FloatT>&) 
            { 
                // <Conversion logic here.>
            }
        };
    }
    
    // Convenient user-interface function, deduces `T`.
    template<typename T>
    auto to_json(const T& x)
    {
        // Instantiate a temporary `json_converter` and call `to_json`.
        return impl::json_converter<std::decay_t<T>>{}.to_json(x);
    }
    

    用法:

    KalmanFilter<4, 4, 4, double> kf{/* ... */};
    auto result = to_json(kf);
    
        2
  •  1
  •   Oktalist    9 年前

    或者我必须使用不同声明的toJson,比如

    template<int A, int B, int C, typename FloatT>
    Json::Value toJson(const KalmanFilter<A, B, C, FloatT>&);
    

    ?

    是的,这正是你需要的。

    进入函数模板专业化,您会感到困惑。这里绝对没有理由使用函数模板专门化。如果您想要其他类型的转换,只需以相同的方式添加它们:

     template<double A, double B, double C, typename T>
     Json::Value toJson(const OtherFilter<A, B, C, T>&);
    

    如果在不同的命名空间中有不同的类型,那么使用具有多个专门化的单个函数模板将无法与ADL合作。每个 toJson 函数需要位于其参数类型的命名空间中。更不用说,您可能会对编译器实际选择使用哪种专门化感到惊讶。普通的过载解决方案并不令人惊讶。