如何专门化容器和枚举的模板

供应

我试图专门针对枚举类型和stl容器类型的简单功能。SFINAE的想法适用于使用enable_if的枚举,但是对于stl容器,类似的技术不起作用(我知道依靠value_type的存在并假设它不是一个好主意,但这不是重点。)

template <typename T, typename = void>
    struct wrapper {
        static T getValue()
        {
            std::cout<<"\n WRAPPER DEFAULT VERSION IS CALLED.\n";
            return T();
        }
    };

    template<typename T>
    struct wrapper<T,typename std::enable_if<std::is_enum<T>::value>::type>{
        static T getValue()
        {
            std::cout<<"\n WRAPPER ENUM VERSION IS CALLED.\n";
            return T();
        }
    };

    template<typename Container>
    struct wrapper<Container, typename Container::value_type> {
        static Container getValue()
        {
            std::cout<<"\n WRAPPER CONTAINER VERSION IS CALLED.\n";
            return Container();
        }
    };


int main()
{
    //En is an enum type
    En en = (En) wrapper<En>::getValue(); //Prints ENUM VERSION

    std::vector<int> vec;
    vec = wrapper<std::vector<int>>::getValue(); //Prints DEFAULT VERSION
}

请让我知道为什么第二个调用进入默认实现?

解:

多亏了Sam Varshavchik,我才发现我错过了第二个参数应该解析为void的要点(就像在enable_if :: type的情况下那样),否则我将不得不显式传递第二个参数以使我的调用解析为容器版: wrapper<std::vector<int>, int>::getValue();

为了使原始版本能够正常工作(C ++ 17之前的void_t不可用),我根据容器定义了迭代器类型的事实来创建自己的类型特征:

    template <typename T1, typename T2 = void>
    struct container_trait
    {};

    template <typename T1>
    struct container_trait<T1, typename T1::iterator> {
        typedef void type;
    };

现在我的包装器容器版本变为:

    template<typename Container>
    struct wrapper<Container, typename container_trait<Container, typename Container::iterator>::type> {
        static Container getValue(const rapidjson::Value& rjv)
        {
            std::cout<<"\n WRAPPER CONTAINER VERSION IS CALLED.\n";
            return Container();
        }
    };

现在,相同的调用可以正常工作:

vec = wrapper<std::vector<int>>::getValue(); //Prints CONTAINER VERSION

山姆·瓦尔沙夫奇克

第二次调用默认实现的原因非常简单。

只需手动计算出如何为容器版本模板的参数推导参数:

template<typename Container>
struct wrapper<Container, typename Container::value_type>

您正在实例化以下模板:

wrapper<std::vector<int>>

所以:

1)Containerstd::vector<int>

2)Container::value_typeint

因此,该专业化变为:

struct wrapper<std::vector<int>, int>

但是,您仅在调用:

wrapper<std::vector<int>, void>

因为它void是第二个模板参数的默认值,所以它与错误的专业化匹配。

解决方案非常简单,容器专门化应该是:

#include <type_traits>

template<typename Container>
struct wrapper<Container, std::void_t<typename Container::value_type>> {

std::void_t是C ++ 17,stackoverflow.com上还有其他问题,说明了如何针对较早的C ++标准实现它。完整的例子:

#include <vector>
#include <iostream>
#include <type_traits>

enum En {};

template <typename T, typename = void>
struct wrapper {
        static T getValue()
        {
        std::cout<<"\n WRAPPER DEFAULT VERSION IS CALLED.\n";
        return T();
        }
};

template<typename T>
struct wrapper<T,typename std::enable_if<std::is_enum<T>::value>::type>{
        static T getValue()
        {
        std::cout<<"\n WRAPPER ENUM VERSION IS CALLED.\n";
        return T();
        }
};

template<typename Container>
struct wrapper<Container, std::void_t<typename Container::value_type>> {
        static Container getValue()
        {
        std::cout<<"\n WRAPPER CONTAINER VERSION IS CALLED.\n";
        return Container();
        }
};


int main()
{
    //En is an enum type
    En en = (En) wrapper<En>::getValue(); //Prints ENUM VERSION

    std::vector<int> vec;
    vec = wrapper<std::vector<int>>::getValue(); //Prints DEFAULT VERSION
}

结果:

WRAPPER ENUM版本已调用。

包装容器版本已调用。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

模板专门化和实例化

来自分类Dev

如何专门化模板子类?

来自分类Dev

如何专门化模板成员函数?

来自分类Dev

根据枚举成员的值来专门化模板

来自分类Dev

如何使用模板模板参数专门化类模板?

来自分类Dev

如何专门化用于const和非const容器的模板?

来自分类Dev

如何使用模板临时参数专门化模板

来自分类Dev

如何专门化模板函数以区分void和non-void函数参数

来自分类Dev

如何专门化模板类成员函数?

来自分类Dev

如何测试是否存在模板功能专门化

来自分类Dev

如何使用运算符来专门化模板?

来自分类Dev

如何使用 no-typename 参数专门化模板?

来自分类Dev

模板专门化中的double template <>

来自分类Dev

使用指令专门化的模板

来自分类Dev

模板成员变量专门化

来自分类Dev

模板成员函数专门化

来自分类Dev

模板类-成员函数专门化

来自分类Dev

部分模板专门化的意外结果

来自分类Dev

C ++:数组的功能模板专门化

来自分类Dev

模板类-成员函数专门化

来自分类Dev

您如何专门化非模板化类中没有参数的模板化方法?

来自分类Dev

在模板化类中专门化模板化结构

来自分类Dev

使用类模板的内部类模板专门化模板

来自分类Dev

如何通过使用可变参数模板参数来专门化元组的类模板?

来自分类Dev

如何使用type_traits或模板功能专门化来巩固模板方法

来自分类Dev

您如何专门化非模板类中没有参数的模板方法?

来自分类Dev

如何在模板类中专门化模板成员函数?

来自分类Dev

如何专门化模板类中的模板成员函数(已指定)?

来自分类Dev

如何使用type_traits或模板功能专门化来巩固模板方法

Related 相关文章

热门标签

归档