Home :C++: Exposing specialized templates only
Reply: 2

:C++: Exposing specialized templates only

Stepan Andreenko
1#
Stepan Andreenko Published in 2018-02-13 20:47:08Z

I would like to create my own serialization using the following class. I want to have general protected << operator and to publish only some exactly typed specializations:

class TBinaryOut
{
public:
    virtual void write(const char * ptr, size_t count) = 0;
protected:
    template <typename T>
    TBinaryOut & operator<< (const T& i)
        { write((const char *)(void *)&i, sizeof(T)); return *this; }
public:
    template <unsigned int> TBinaryOut & operator << (const unsigned int& i);
    template <int> TBinaryOut & operator << (const int& i);
    template <uint8_t> TBinaryOut & operator << (const uint8_t& i);
    template <int8_t> TBinaryOut & operator << (const int8_t& i);
};

Unfortunately, this does not work. If I write

int A = 10;
Stream << A;

VS2013 compiler always tries to instantiate generic protected template and therefore gives an error. What should I do to make it work correctly?

Edit: If I write specializations as

template <> TBinaryOut & operator << (const unsigned int& i);

everything compiles OK, but I get unresolved linker errors for this.

liliscent
2#
liliscent Reply to 2018-02-13 21:04:28Z

If you want to use a templated implementation for many but not all types, you can use a trait to determine which ones are allowed.

#include <cstdint>
#include <cstdlib>
#include <type_traits>

template<class T>
struct is_exposed : public std::false_type{};

template<> struct is_exposed<int> : public std::true_type{};

template<> struct is_exposed<uint8_t> : public std::true_type{};

/* ... */

class TBinaryOut
{
public:
    virtual void write(const char * ptr, size_t count);
public:
    template <typename T, std::enable_if_t<is_exposed<T>::value, int> = 0>
    TBinaryOut & operator<< (const T& i)
        { write((const char *)(void *)&i, sizeof(T)); return *this; }
};

int main() {
    TBinaryOut t;
    int A = 10;
    t << A; // Ok, because int is explicitly exposed

    short b = 20;
    //t << b; // Error, because short is not exposed
}
Stepan Andreenko
3#
Stepan Andreenko Reply to 2018-02-13 22:24:04Z

Just moving the answer out of the @DrewDormann comment - I should write specialized templates as:

template <> TBinaryOut & operator << (const uint8_t& i);

Edit: This does not work. Compilation goes OK, but I get this specialization unresolved during linking.

Also thanks to @liliscent for another elegant solution (following).

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.328721 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO