2016-05-15 38 views
0

我努力做到以下几点:错误无法接通块

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<T> & bar = *ptr; 

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

+0

“未执行”是不一样的“未编译”。 –

+1

这是一个模板,编译器必须为其生成代码,即使存在会阻止模板初始化的条件。 – Rakete1111

+0

好的,我明白了。但我怎么能以正确的方式做到这一点? – Exagon

回答

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模板,一个用于当模板参数是一个子类,它不移动的情况,和一个。

这两个版本的foo()可能会有大量的通用代码。因此,您可能需要在这里做更多的工作,将通用代码分解为独立的模板函数,您将从foo() s中调用。

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  
}