【问题标题】:Non-type template parameter and std::enable_if_t非类型模板参数和 std::enable_if_t
【发布时间】:2019-02-08 16:53:28
【问题描述】:

我正在尝试做一些持久性的东西,我有一个这样的结构:

struct EntityPersistence {
    template <typename Archive>
    void persist(Archive &ar, Entity &)
    {
    }
};

然后,在我的类实体中,我有这样的东西:

static const EntityPersistence entityPersistence;

PERSISTENCE_CUSTOM(Entity, entityPersistence)

这个宏做了这样的事情:

#define PERSISTENCE_CUSTOM(Base, customPersistence)  \
SERIALIZE(Base, customPersistence)

循序渐进……(这就是重要的事情发生的地方)

#define SERIALIZE(Base, customPersistence)
template <class Archive>
void serialize(Archive& ar)
{
    serialize_custom(ar);
}

template <class Archive, class Base, decltype(customPersistence) &persistence = customPersistence>
std::enable_if_t<std::is_base_of<cereal::InputArchive<Archive>, Archive>::value && has_deserialize<std::remove_const<decltype(customPersistence)>::type, Archive&, Base&>() == true, void>
serialize_custom(Archive &ar)
{
    persistence.deserialize(ar, const_cast<Base&>(*this));                                    
}

一些缺失的代码用于检查 Persistance 结构中实现了哪些函数,以便在编译时分支执行代码:

template<class> struct sfinae_true : std::true_type{};

template<class T, class A0, class A1>
static auto test_deserialize(int)
-> sfinae_true<decltype(std::declval<T>().deserialize(std::declval<A0>(), std::declval<A1>()))>;
template<class, class A0, class A1>
static auto test_deserialize(long) -> std::false_type;

template<class T, class A0, class A1>
static auto test_persist(int)
-> sfinae_true<decltype(std::declval<T>().persist(std::declval<A0>(), std::declval<A1>()))>;
template<class, class A0, class A1>
static auto test_persist(long) -> std::false_type;

template<class T, class Arg1, class Arg2>
struct has_deserialize : decltype(::detail::test_deserialize<T, Arg1, Arg2>(0)){};
template<class T, class Arg1, class Arg2>
struct has_persist : decltype(::detail::test_persist<T, Arg1, Arg2>(0)){};

有问题的错误:

In member function ‘std::enable_if_t<(std::is_base_of<cereal::InputArchive<Archive>, Archive>::value && (has_deserialize<EntityPersistence, Archive&, Entity&>() == true)), void> Entity::serialize_custom(Archive&)’:
error: ‘const struct EntityPersistence’ has no member named ‘deserialize’
     persistence.deserialize(ar, const_cast<Base&>(*this));                                    \
                 ^

deserialize 函数在 EntityPersistence 中不存在,但如果 enable_if_t 能够完成它的工作,那么这个 serialize_custom 专业化也不应该。 我已经在这段代码之外测试了has_deserialize struct,它运行良好。这可能与 serialize_custom 函数中的非类型模板参数有关吗?也许它是在 enable_if_t 之前评估的?

提前致谢

【问题讨论】:

    标签: c++ templates sfinae enable-if


    【解决方案1】:

    不确定,我有足够的元素可以尝试但是...检查persistenceserialize_custom() 的模板参数)而不是customPersistence(这不是serialize_custom() 的模板参数呢?

    我的意思是……下面呢?

    template <class Archive, class Base,
              decltype(customPersistence) & persistence = customPersistence>
    std::enable_if_t<std::is_base_of<cereal::InputArchive<Archive>, Archive>::value                   
                  && has_deserialize<std::remove_const<decltype(persistence)>::type,
                                  Archive&, Base&>() == true> //^^^^^^^^^^^
    serialize_custom(Archive &ar)
    {
        persistence.deserialize(ar, const_cast<Base&>(*this));                                    
    }
    

    【讨论】:

    • 我必须将其编写如下以使其编译:...has_deserialize&lt;typename std::remove_const&lt;decltype(persistence)&gt;::type... 但它不起作用。还在抱怨不存在序列化/反序列化方法
    【解决方案2】:

    我终于用中介方法解决了这个问题(以防万一有人感兴趣):

    template <class Archive>
    void serialize(Archive& ar)
    {
        serialize_custom_helper(ar);
    }
    
    template <class Archive, decltype(customPersistence)& persistence = customPersistence>        \
    void serialize_custom_helper(Archive& ar)
    {
        serialize_custom(ar, persistence);
    }
    
    template <class Archive, class Base, class P>
    std::enable_if_t<std::is_base_of<cereal::InputArchive<Archive>, Archive>::value && has_deserialize2<P, Archive&, Base&>() == true, void> 
    serialize_custom(Archive &ar, P& persistence)
    {
        persistence.deserialize(ar, const_cast<Base&>(*this));
    }
    
    ...
    

    【讨论】:

      猜你喜欢
      • 2021-03-20
      • 2021-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-06
      相关资源
      最近更新 更多