简体   繁体   中英

Template specialization for templatized types

I'm quite new to the realm of c++ template programming.

I understand that I can specialise function templates, eg in my case a toJson -function template that I want to use using ADL.

Eg

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

where Json::Value is provided by the JsonCPP-Library.

Now I can specialise this for "normal" types like this:

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

Great.

However, I have a type, KalmanFilter<3, 3, 3, double> (obviously, this is fully parametrised) which in turn has several Eigen3-Matrices as type, who's dimension is determined based on the integral template arguments in KalmanFilter. I would like to specialise toJson like this:

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

Maybe there is a different way of achieving this (eg Eigen overloads the std::ostream operator<< generically for all its types).

Or do I have to use a differently declared toJson, like

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

?

I would solve this problem by using a template struct and specializing it, instead of specializing a function template, 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);
}

Usage:

KalmanFilter<4, 4, 4, double> kf{/* ... */};
auto result = to_json(kf);

Or do I have to use a differently declared toJson, like

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

?

Yes, that's exactly what you need.

You're confusing yourself by getting into function template specialization. There's absolutely no reason to use function template specialization here. If you want conversions for other types, just add them in the same way:

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

If you have different types in different namespaces, then using a single function template with multiple specializations will not cooperate with ADL. Each toJson function needs to be in the namespace of its parameter type. Not to mention that you could potentially be surprised by which specialization the compiler actually chooses to use. Ordinary overload resolution is less surprising.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM