【问题标题】:Template partial specialisation not working with typedefs模板部分专业化不适用于 typedef
【发布时间】:2014-02-10 06:49:32
【问题描述】:

在这个例子中:

template<typename T>
struct ConditionalValue
{
    typedef boost::optional<T> type;
};

template<typename T>
struct FindRootValueType
{
    typedef typename T::root_type type;
};

template<typename T>
struct FindRootValueType<typename ConditionalValue<T>::type>
{
    typedef typename ConditionalValue<T>::type type;
};

template<typename T>
struct Base
{
    typedef T value_type;
    typedef typename FindRootValueType<value_type>::type root_type;
    std::vector<value_type> data;
};

template<typename T>
struct A : public Base<typename ConditionalValue<T>::type>
{
};

template<typename T>
struct B : public Base<A<T>>
{
};

template<typename T>
struct C : public Base<B<T>>
{
};

// C<int>::value_type == B<int>
// C<int>::data == std::vector<B<int>>
// C<int>::data ~= std::vector<std::vector<std::vector<boost::optional<int>>>>
// C<int>::root_type == boost::optional<int>

ConditionalValue 是一个模板别名,它只是尝试为boost::optional 提供一个替代名称(这样可以使用其他东西来替换它),FindRootValueType 是一个元函数,旨在遍历一系列类型其定义类似于底部显示的定义,直到它停在boost::optional,然后简单地返回。

但是,正如所写的那样,这不起作用(至少在 VS2008 中不起作用)。要修复它,FindRootValueType 的特化必须显式使用boost::optional&lt;T&gt;,而不是应该与其等效的 typedef。 (这违背了仅在一个地方指定底层实现类型的目标。)

这是编译器错误还是应该不起作用?还是我只是做错了什么?有没有更好的方法来编写它以使其按预期工作?

我也尝试过这样颠倒逻辑:

template<typename T>
struct FindRootValueType
{
    typedef T type;
};

// define Base here

template<typename T>
struct FindRootValueType<Base<T>>
{
    typedef typename T::root_type type;
};

// define A here

template<typename T>
struct FindRootValueType<A<T>>
{
    typedef T type;
};

// define B, C here (no specialisation)

但这也不起作用(我认为是因为专业化不遵循基本类型,或者可能只是定义的顺序)。我不想专门针对 B、C 等。

(顺便说一句,在上述两种情况下,“不工作”意味着产生了编译器错误,表明它使用的是FindRootValueType 的基本定义,而不是专门化。)

【问题讨论】:

    标签: c++ templates metaprogramming template-specialization


    【解决方案1】:

    this answer 相关问题链接的启发,我尝试了以下方法,它似乎有效:

    template<typename T>
    struct HasRootType
    {
    private:
        typedef char no;
        struct yes { no m[2]; };
    
        static T* make();
        template<typename U>
        static yes check(U*, typename U::root_type* = 0);
        static no check(...);
    
    public:
        static bool const value = sizeof(check(make())) == sizeof(yes);
    };
    
    template<typename T, bool = HasRootType<T>::value>
    struct FindRootValueType
    {
        typedef typename T::root_type type;
    };
    
    template<typename T>
    struct FindRootValueType<T, false>
    {
        typedef T type;
    };
    
    // define Base, A, B, C, etc here
    

    因此将问题重新定义为“遍历类型,直到找到没有root_type 的类型,然后返回该类型”。不过,我仍然很好奇为什么基于 typedef 的专业化似乎不起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-23
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多