无法访问if块时出错

时间:2016-05-15 14:22:47

标签: c++ templates c++11

我正在尝试执行以下操作:

template <class T>
void foo(T * ptr){
    ...a lot of code ...
    if(std::is_base_of<Bar<T>,T>::value){
        Bar<T> & bar = *ptr;
        ...a lot of code ...
    }
    ...a lot of code    
}

如果我用一个Bar的子类编译这个函数,一切正常,但是如果我尝试使用哪个isnt进行编译,我会在

处收到错误
Bar<T> & bar = *ptr;

线。 这是怎么回事,因为当T不是Bar<T>的子类时,这条线是否会被执行? 如果这不是通常的方法,我怎样才能以正确的方式实现这一目标?

2 个答案:

答案 0 :(得分:1)

因为Bar<T>不是T的子类,

Bar<T> & bar = *ptr;

这会导致编译错误。事实上,它被包含在一个if()语句中,该语句的计算结果为false,并且代码的这一部分永远不会被执行,并不会改变这一事实。

这里的正确方法是专门化模板。

这些方面的东西:

template <class T, bool is_subclass=std::is_base_of<Bar<T>,T>::value>
void foo(T * ptr);

template <class T>
void foo<T, true>(T * ptr){
    ...a lot of code ...

    Bar<T> & bar = *ptr;
    ...a lot of code ...

    ...a lot of code    
}

template <class T>
void foo<T, false>(T * ptr){
    ...a lot of code ...

    ...a lot of code    
}

您现在有两个不同版本的foo模板,一个用于模板参数是子类的情况,另一个不是。{/ p>

foo()的两个版本都可能包含大量公共代码。因此,您可能需要在此处做更多的工作,将公共代码分解为他们自己的独立模板函数,您将从foo()调用它们。

答案 1 :(得分:1)

这可以通过多种方式实现,例如标签调度:

template <class T>
void bar(T* ptr, std::true_type)
{
    // ...a lot of code ...
}

template <class T>
void bar(T*, std::false_type)
{
    // do nothing
}

template <class T>
void foo(T * ptr){
    //...a lot of code ...
    bar(ptr, std::is_base_of<Bar<T>,T>{});
    //...a lot of code    
}