我试图将模板化方法限制为允许类型及其“重复”样式的给定列表。

typedef boost::mpl::set<bool, int, double> allowedTypes;

class Foo
{
    typedef boost::mpl::set<bool, int, double> allowedTypes;
    template<class T>
    void some_templated_method()
    {
       BOOST_MPL_ASSERT((boost::mpl::has_key<allowedTypes, T>));
    }
}


// main.cpp
Foo foo;
struct restricted_type{};
foo.some_templated_method<restricted_type>(); // Compiles, why ?!

除此之外,我想知道如何自动过滤允许类型的重复版本。对于重复版本,我的意思是指他们的std::vector<T>表示形式,但未在mpl::set中明确显示

例如
typedef boost::mpl::set<bool,
                        int,
                        double,
                        std::vector<bool>,
                        std::vector<int>,
                        std::vector<double> > allowedTypes;

最佳答案

您总是可以自动创建一个包含原始集合及其容器包装副本的序列。

为此,我们需要一元lambda:

template <template <typename...> class Container>
struct MakeContainerOfT {
    template <typename T>
    struct impl {
        using type = Container<T>;
    };
 };

这可以处理除映射(它们需要一个值类型)和数组(有一个非类型模板参数)之外的每个容器。作为奖励,这是制造大小为N的数组的工厂:
template <std::size_t N>
struct ArrayOfT {
    template <typename T>
    struct impl {
        using type = std::array<T, N>;
    };
};

现在,我们需要一个设施,将这个lambda(或任何其他一元lambda)应用到我们给定的任何容器的集合中。
template <typename Sequence, template <typename> class Transform>
struct TransformedSequenceBuilder {
    using type = typename boost::mpl::reverse_fold<Sequence,
                                      boost::mpl::set0<>,
                                      boost::mpl::insert<boost::mpl::_1,
                                                         Transform<boost::mpl::_2>>>::type;
};

我们最终可以继续使用“累加器”,该累加器将对可变的lambda序列执行此操作:
template <typename Sequence, template <typename> class... Transforms>
struct MakeFullSequence;

template <typename Sequence, template <typename> class Transform, template <typename> class... Tail>
struct MakeFullSequence<Sequence, Transform, Tail...> {

    using type = typename boost::mpl::reverse_fold<typename MakeFullSequence<Sequence, Tail...>::type,
                                      typename TransformedSequenceBuilder<Sequence, Transform>::type,
                                      boost::mpl::insert<boost::mpl::_1, boost::mpl::_2>>::type;
};

template <typename Sequence>
struct MakeFullSequence<Sequence> {
    typedef Sequence type;
};

最后一步是为您感兴趣的容器定义别名:
template <typename Sequence>
using wrapped_set = typename MakeFullSequence<Sequence,
                                              ContainerOfT<std::vector>::template impl,
                                              ContainerOfT<std::set>::template impl//,
                                              /* any transformation you fancy here */>::type;

为了测试这一点,我们可以执行相等性测试:
using le_set = boost::mpl::set<int, double, char>;
using le_vector_set = boost::mpl::set<std::vector<int>, std::vector<double>, std::vector<char>>;
using le_set_set = boost::mpl::set<std::set<int>, std::set<double>, std::set<char>>;

using le_transformed_set = wrapped_set<le_set>;
using le_manually_transformed_set = boost::mpl::joint_view<boost::mpl::joint_view<le_set, le_set_set>::type, le_vector_set>::type;

std::cout << boost::mpl::equal<le_transformed_set,
                               le_manually_transformed_set>::value;

这样的用法就非常简单:用户仅提供Set类型的“原始”集,并且您每次需要时就将逻辑分支到wrapped_set<Set>上:
class Foo
{
    typedef boost::mpl::set<bool, int, double> allowedTypes;
    template<class T>
    void some_templated_method()
    {
       BOOST_MPL_ASSERT((boost::mpl::has_key<wrapped_set<allowedTypes>, T>));
    }
};

您可以在此处找到演示我们最终以原始集合, vector 包装的集合和集合包装的集合的并集为例的演示:

通过这种设计,您还可以添加任何其他您喜欢的“重复口味”。引用(resp。const)输入类型的对应项?只需传递std::add_lvalue_reference(或者std::add_const)!

关于c++ - 声明是否允许模板参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44624301/

10-17 01:39