[英]Iteratively check function presence at compile time
關於我現在面臨的一個問題,我有一個問題。 在C ++中,我創建了一個幫助程序,能夠檢測給定模板方法的模板參數是否實現了serialize
方法(boost序列化實現)。 幫助程序可以完美地與我可以拋出的大多數類一起工作,但是我想擴展它的功能如下。
讓我們假設我有一個具有serialize方法的Foo
類。 我希望我可以傳遞任何嵌套支持的容器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
#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> {};
根據Piotr非常棒的建議,我已經擴展了他的解決方案,以便與boost trivially serialisable類型兼容(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, "!");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.