如何使用模板类的子类来推断C ++中模板函数的模板参数?

时间:2012-03-01 09:35:03

标签: c++ templates

这可能非常愚蠢......

如果我有这样的模板类A,

template <class T1, class T2>
struct A
{
    T1 a;
    T2 b;
};

并且函数可以使用,

template <class T1, class T2>
void foo(A<T1, T2> *p)
{
}

现在我是A的子类,

struct B : A<int, int>
{
};

B b[100];

我无法推断出模板参数...

foo(b);

我必须这样写,

foo((B *)b);

或者像这样,

foo<int, int>(b);

现在还有更多, 我希望foo可以接受除A之外的其他东西并将它们视为A

template <class T>
struct A<T, void>
{
    T a;
};

template <class T>
void foo(T *p)
{
    foo((A<T, void> *)p);
}

现在除非我这样写,否则后来的foo被称为......

foo<int, int>(b);
  1. 如何从子类数组中轻松推导出模板参数?
  2. 在查找重载函数时,如何让子类比其他类具有更高的优先级?

  3. 这似乎可以做到

    template <class T>
    struct is_A_derived
    {
        typedef char (&yes)[1];
        typedef char (&no)[2];
    
        template <class T1, class T2>
        static yes test(A<T1, T2> *);
        static no test(...);
    
        template <class T1, class T2>
        static A<T1, T2> get_type(A<T1, T2> *);
        static A<T, void> get_type(...);
    
        template <class T1, class T2>
        static A<T1, T2> base_type(A<T1, T2> *);
        static int base_type(...); // guess or maybe hope this "int" is never used
    
        static const bool value = sizeof(test((T *)0)) == sizeof(yes);
        static const bool identical = value && sizeof(base_type((T *)0)) == sizeof(T);
    
        typedef typename std::conditional<identical, decltype(get_type((T *)0)), A<T, void>>::type type;
    };
    

2 个答案:

答案 0 :(得分:1)

请注意,此代码失败。您不能以多态方式使用C样式数组(无论模板如何)。

也就是说,您无法将数组 - B视为 - A数组。

如果你写p[1],你认为会怎么样?嗯,内部发生以下情况:

*(p + 1)

指针算术。现在,编译器将+ 1进一步翻译为sizeof A个字节的增量。但是您的数据结构不是sizeof A大,而是sizeof B!因此p[1]将指向内存中的错误位置。

因此,编译器(完全是偶然!)通过禁止此调用来做正确的事情。

答案 1 :(得分:0)

在第一种情况下,实际上存在将B数组衰减到A *指针的危险,以防您在A *指针上发生指针运算。

令我惊讶的是它没有解决但可能是一个很好的安全功能,以防你计划在A数组上执行一个函数,这对于B数组不起作用。

您可以foo( &b[0] )而不是投射或显式模板。

在后一种情况下,如果它与A模板上的函数同名,则现在使用T *上的函数foo使事情变得复杂。

一旦你添加了第二个foo,B上的调用确实会选择第二个foo,因为它现在变成了一个完美的匹配。使用聪明的SFINAE技术可以赋予子类更高的优先级,以查看它是否为A。一般来说,除非你真的需要,否则我会避免使用它。