0

I am trying to write a template class using SFINAE to convert from a map to json and vice versa. The idea is to restrict the class to maps that have an integral value type or convertible to int, i.e. enums, but I'm having problems compiling my class.

Here's my code so far:

MapToJsonConvertor.h:

#ifndef COMMON_MAPTOJSONCONVERTOR_H_
#define COMMON_MAPTOJSONCONVERTOR_H_

#include <Poco/JSON/Object.h>
#include <Poco/JSON/Parser.h>
#include <Poco/Dynamic/Var.h>
#include <Poco/JSON/Stringifier.h>
#include <map>
#include <type_traits>


template<typename T,
    typename = typename std::enable_if<std::is_convertible<T, int>::value, T>::type>
class MapToJsonConvertor
{
public:
    MapToJsonConvertor(const std::map<int, T> &mapFrom): mMap(mapFrom)
    {}
    MapToJsonConvertor(const Poco::JSON::Object::Ptr &jsonObject): mJsonObject(jsonObject)
    {}
    Poco::JSON::Object::Ptr Convert(const std::string &rootName);
    //std::map<int, T> Convert(const Poco::JSON::Object::Ptr &jsonObject);

private:
    std::map<int, T> mMap;
    Poco::JSON::Object::Ptr mJsonObject;
};


#endif /* COMMON_MAPTOJSONCONVERTER_H_ */

MapToJsonConvertor.cpp

#include "MapToJsonConvertor.h"

template<typename T>
Poco::JSON::Object::Ptr MapToJsonConvertor<T>::Convert(const std::string &rootName)
{
    Poco::JSON::Object::Ptr root = new Poco::JSON::Object();
    Poco::JSON::Array::Ptr array = new Poco::JSON::Array();

    if (!mMap.empty())
    {
        for (auto &elem : mMap)
        {
            Poco::JSON::Object::Ptr elemPtr = new Poco::JSON::Object();
            elemPtr->set("key", elem.first);
            elemPtr->set("value", static_cast<int>(elem.second));
            array->add(elemPtr);
        }
    }

    root->set("elements", array);

    return root;
}

The error I get is:

../src/Common/MapToJsonConvertor.cpp:12:83: error: invalid use of incomplete type ‘class MapToJsonConvertor<T>’ Poco::JSON::Object::Ptr MapToJsonConvertor<T>::Convert(const std::string &rootName)
^
In file included from ../src/Common/MapToJsonConvertor.cpp:9:0: ../src/Common/MapToJsonConvertor.h:21:7: note: declaration of ‘class MapToJsonConvertor<T>’ class MapToJsonConvertor ^

I'm using the Poco libraries for Json building.

I'm still new to template metaprogramming with SFINAE, so I would appreciate some help. What am I doing wrong?

Raymond Chen
  • 44,448
  • 11
  • 96
  • 135
jignatius
  • 6,304
  • 2
  • 15
  • 30
  • Are you sure that's the error message that matches the code? The line numbers are not in sync. (The error message says that the `#include` was on line 9, but in the code you posted, the `#include` is on line 1.) – Raymond Chen Oct 04 '19 at 22:48
  • @JaMiT It happens. This message will self destruct when I remember to do it. – user4581301 Oct 04 '19 at 23:40

1 Answers1

1

So first of all, templates should be implemented in the header file as explained here.

Besides that, your problem lies in the template signature of your function definition in your source file. You are using a 2nd template parameter in your class for SFINAE so you have to specify that template parameter in the definition as well:

template<typename T, typename U> // note the 2nd parameter
Poco::JSON::Object::Ptr MapToJsonConvertor<T, U>::Convert(const std::string &rootName)
{
    ...
}
Timo
  • 9,269
  • 2
  • 28
  • 58