Итеративно проверять наличие функции во время компиляции - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть вопрос по одной проблеме, с которой я сталкиваюсь сейчас. В C ++ я создал помощника, способного определить, реализует ли параметр шаблона данного метода шаблона метод serialize (ускоренная реализация сериализации). Помощник безупречно работает с большинством классов, которые я могу использовать, но я хочу расширить его функциональность следующим образом.

Предположим, у меня есть класс Foo, у которого есть метод serialize. Я бы хотел передать ему любой вложенный поддерживаемый контейнер vector<list<array<Foo,8>>>, учитывая, что vector, list и array обеспечивают метод serialize.

Как итеративно углубиться в содержащиеся типы до типа, не реализующего элемент value_type?

Заранее спасибо

Вот мое текущее решение:

namespace check
{
///A set of classes and struct to be sure the serialised object is either trivial or implementing custom serialize
template <class Type, class Archive, typename = typename std::enable_if<std::is_class<Type>::value>::type>
class is_boost_serializable
{
 private:
  struct TypeOverloader {
    void serialize(Archive& ar, const unsigned int version) {}
  };
  struct TypeExt : public Type, public TypeOverloader {
  };
  template <typename T, T t>
  class DeductionHelper
  {
  };

  class True
  {
    char m;
  };
  class False
  {
    True m[2];
  };

  template <typename TestType>
  static False deduce(TestType*, DeductionHelper<void (TypeOverloader::*)(), &TestType::serialize>* = 0);
  static True deduce(...);

 public:
  static const bool value = (sizeof(True) == sizeof(deduce((TypeExt*)(0))));
};
} // namespace check

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Следуя замечательному предложению Петра, я расширил его решение, чтобы оно было совместимо также с тривиально сериализуемыми типами boost (int, char, double ...).

Здесь, после моего индивидуального решения.

Ура и спасибо!

#include <type_traits>
#include <utility>
#include <vector>
#include <list>
#include <array>
#include <cassert>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/set.hpp>
#include <boost/type_traits.hpp>

struct Arc
{
};

struct Foo
{
    int pippo = 0;

    friend class boost::serialization::access;

    template <class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar &pippo;
    }
};

struct Bar
{
};

template <typename...>
using void_t = void;

template <typename Type, typename Archive = boost::archive::binary_oarchive, typename = void_t<>>
struct is_boost_serializable_base : std::false_type
{
};

template <class Type, typename Archive>
struct is_boost_serializable_base<Type, Archive,
                                  void_t<decltype(std::declval<Type &>().serialize(std::declval<Archive &>(), 0))>>
    : std::true_type
{
};

template <typename Type, typename Archive>
struct is_boost_serializable_base<Type, Archive,
                                  typename std::enable_if<boost::serialization::is_bitwise_serializable<Type>::value>::type>
    : std::true_type
{
};

template <typename Type, typename Archive = boost::archive::binary_oarchive, typename = void_t<>>
struct is_boost_serializable
    : is_boost_serializable_base<Type, Archive>
{
};

template <typename Type, typename Archive>
struct is_boost_serializable<Type, Archive, void_t<typename Type::value_type>>
    : is_boost_serializable<typename Type::value_type, Archive>
{
};

template <typename Type>
struct is_boost_serializable<Type, boost::archive::binary_oarchive, void_t<typename Type::value_type>>
    : is_boost_serializable<typename Type::value_type, boost::archive::binary_oarchive>
{
};

int main()
{
    static_assert(is_boost_serializable<Foo, Arc>::value, "!");
    static_assert(is_boost_serializable<std::vector<std::list<std::array<Foo, 8>>>, Arc>::value, "!");
    static_assert(is_boost_serializable<std::vector<std::list<std::array<int, 8>>>, Arc>::value, "!");
    static_assert(not is_boost_serializable<std::vector<std::list<std::array<Bar, 8>>>, Arc>::value, "!");
}
0 голосов
/ 03 сентября 2018
#include <utility>
#include <type_traits>

template <typename...>
using void_t = void;

template <typename Type, typename Archive, typename = void_t<>>
struct is_boost_serializable : std::false_type {};

template <typename Type, typename Archive>
struct is_boost_serializable<Type, Archive,
    void_t<decltype(std::declval<Type&>().serialize(std::declval<Archive&>(), 0))>>
    : std::true_type {};

template <typename Type, typename Archive, typename = void_t<>>
struct nested_is_boost_serializable
    : is_boost_serializable<Type, Archive> {};

template <typename Type, typename Archive>
struct nested_is_boost_serializable<Type, Archive, void_t<typename Type::value_type>>
    : nested_is_boost_serializable<typename Type::value_type, Archive> {};

DEMO

...