如何将模板类型作为参数传递给非模板函数?

时间:2017-01-19 23:22:47

标签: c++ templates

我的功能模板存在以下问题。如果我有这样的功能模板,其中T可以是ClassAClassB

template<typename T, bool flag>
void function(T& someT){
    if(flag){    /*If 'flag' is true, 'someT' MUST be of type ClassA*/
        nonTemplateFunction1(someT);
    }
    else{    /*Else 'someT' must be of type ClassB*/
        nonTemplateFunction2(someT);
    }
}

在其他文件中我有

void nonTemplateFunction1(ClassA& a){...}

在另一个文件中我有

void nonTemplateFunction2(ClassB& b){...}

现在,如果我调用我的函数模板,编译时出错:

  

错误:没有匹配的成员函数来调用&#39; nonTemplateFunction2&#39;

我想这是因为编译器测试nonTemplateFunction2的调用,例如ClassA作为参数。但这永远不会发生(至少我,程序员,照顾这个)。我怎样才能让我的程序编译?有哪些可能的解决方案?

编辑:更准确的错误:

  

./ tabledata.hh:371:9:错误:没有匹配的成员函数来调用&#39; bulk_insert&#39;                                               bi.bulk_insert(bl,aRel_Vec [j]);

     

../ pax / bulk_insert_pax.hh:21:8:注意:候选功能不可行:没有已知的转换来自&#39; value_type&#39; (又名&#39; NSM_Relation&#39;)到&#39; PAX_Relation&amp;&#39;第二个参数                       void bulk_insert(const BulkLoader&amp; aBulkLoader,PAX_Relation&amp; aRelation);

2 个答案:

答案 0 :(得分:1)

您将编译时决策与运行时决策混合在一起。编译器确实知道someT的类型,是的,但它不会删除if分支。基本上在处理之后,它看起来像这样:

void function(ClassA& someT){
    if(true){
        nonTemplateFunction1(someT);
    }
    // branch will be optimized away, but still 
    // exists
    else{
        // so this is still erroneous code, even though it never runs
        nonTemplateFunction2(someT);
    }
}

因此要么在预处理过程中看到删除不需要的分支的方法,要么使用指针而不是引用或重构您的函数。我不确定选项是什么,我不熟悉模板,但也许你可以将一些标志传递给#ifdef

答案 1 :(得分:0)

在C ++ 17中,您将能够使用if constexpr来执行此操作(您的示例代码按原样):

class ClassA{};
class ClassB{};

void nonTemplateFunction1(ClassA&){}
void nonTemplateFunction2(ClassB&){}

template<typename T, bool flag>
void function(T& someT){
    if constexpr (flag){
        nonTemplateFunction1(someT);
    }
    else{
        nonTemplateFunction2(someT);
    }
}

int main() {
    ClassA a;
    function<ClassA, true>(a);
}

wandbox上查看。

在C ++ 11/14中,你可以依靠sfinae。它遵循一个最小的工作示例:

#include<type_traits>

class ClassA{};
class ClassB{};

void nonTemplateFunction1(ClassA&){}
void nonTemplateFunction2(ClassB&){}

template<typename T>
std::enable_if_t<std::is_same<T, ClassA>::value>
function(T& someT){
    nonTemplateFunction1(someT);
}

template<typename T>
std::enable_if_t<std::is_same<T, ClassB>::value>
function(T& someT){
    nonTemplateFunction2(someT);
}

int main() {
    ClassA a;
    function(a);
}

如果您愿意,也可以使用此功能,并且不希望明确表示类型:

template<typename T>
auto function(T& someT)
-> decltype(nonTemplateFunction1(someT), void()) {
    nonTemplateFunction1(someT);
}

template<typename T>
auto function(T& someT)
-> decltype(nonTemplateFunction2(someT), void()) {
    nonTemplateFunction2(someT);
}