那些if语句是否会在编译时解决?

时间:2017-03-21 09:59:28

标签: c++

嘿伙计们,我几乎无法回答自己的问题。

void someFunc_1(some_known_type_1 bar);
void someFunc_2(some_known_type_2 bar);
void someFunc_3(some_known_type_3 bar);

template < class T, T success> 
void foo(T check) {

    // ...

    auto bar = check;

    if (std::is_same<T, some_known_type_1>::value) {
        someFunc_1((some_known_type_1) bar);
        // ... 
    }
    else if (std::is_same<T, some_known_type_2>::value) {
        someFunc_2((some_known_type_2) bar);
        // ... 
    }
    else if (std::is_same<T, some_known_type_3>::value) {
        someFunc_3((some_known_type_3) bar);
        // ... 
    }

    // ...
}

上面的代码是我的模板函数的最简单版本,用于识别//处理错误。我以这种方式编写这个函数以避免代码重复 - 如果我必须使用模板特化,我会发现在每个版本中部分代码都会重复。

问题:
 1.这些if语句是否会在编译时解决?我想他们会,但我不确定。代码正在编译我测试它。
 2.正常如果我没有使用变量auto bar我最终会遇到每个if语句的编译时错误(类型不匹配)。 因此使用auto变量是一个好主意?或者有更好的吗?(我也尝试使用函数指针,它有效,但它不是性能友好的)





编辑:
好的,你们这么多人告诉我,我可以超载someFunc,所以我就这样做了。但我现在有了新的问题:调用空虚函数是明智的吗?

新版本的代码

///////////////////////////////////
// someFunc:
// - this function in my original code handles different kinds of errors.
// - overloaded for 2 different types (some_known_type_1 & some_known_type_2).
// - with "Catch-all do-nothing" template. 
inline void someFunc (some_known_type_1 bar) {
    // Do something...
}

inline void someFunc (some_known_type_2 bar) {
    // Do something...
}

// Catch-all do-nothing:
template <class T>
inline void someFunc(const T& bar) { /* I am empty... */ };

///////////////////////////////////
// Errchk: (Error check)
template < class T, T success> inline
void errchk(T check) {
    if (check != success) {
        std::cout << "there was an error !!!" << std::endl;

        // Handle Error:
        someFunc( check );
    }
}

// Few additional macros to simplify call to errchk function:
#define ERRCHK_BOOL(_check)   errchk <bool, true> (_check);
#define ERRCHK_TYPE_1(_check) errchk <some_known_type_1, type_1_success_value> (_check);
#define ERRCHK_TYPE_2(_check) errchk <some_known_type_2, type_2_success_value> (_check);

///////////////////////////////////
// program main function:
int main() {
    bool error = false; // this value will be recognized as an error by errchk function;
    ERRCHK_BOOL(error);

    some_known_type_1 error_1 = type_1_error_value // same...
    ERRCHK_TYPE_1(error_1);

    some_known_type_2 error_2 = type_2_error_value // same...
    ERRCHK_TYPE_2(error_2);
}

好的,如果仔细观察,你会看到我没有为bool类型重载someFunc,因此每次使用ERRCHK_BOOL(***);时,我都会调用someFunc的非专业版本模板,这基本上是对空函数的调用。 调用空函数是个好主意吗?

4 个答案:

答案 0 :(得分:4)

C ++ 17 中,您可以使用constexpr if来确保;

如果您无法访问C ++ 17,那么仍然会有一些SFINAE技巧(例如,您可以在某些虚拟额外参数上重载您的函数)来完成这项任务,但可能是{{1}无论如何,语句将在编译时解析。

至于if部分,问题有点不清楚。在这里使用auto bar似乎完全正常,尽管它与auto完全相同。

我不得不说,一个简单的模板专业化可能会让同样的工作更清晰:

T bar

从您的代码中不清楚 - void someFunc_1(some_known_type_1 bar); void someFunc_2(some_known_type_2 bar); void someFunc_3(some_known_type_3 bar); template < class T, T success> void foo(T check) { // ... } template <some_known_type_1 success> void foo<some_known_type_1, success>(some_known_type_1 check) { someFunc_1(check); // ... } 参数有点妨碍 - 但即使是函数重载也足够了(正如其他人所说)。

答案 1 :(得分:2)

您正在做的事情就像手动重新创建功能过载系统一样。让编译器承受压力:

void someFunc(some_known_type_1 bar);
void someFunc(some_known_type_2 bar);
void someFunc(some_known_type_3 bar);

template < class T, T success> 
void foo(T check) {

    someFunc(check);

    // ...
}

答案 2 :(得分:1)

是的,因为在编译时已知Tsome_known_type_1,现代编译器将优化if语句。原因是:它们在过去几十年中被设计用于检测死代码分支并消除它们。如果你没有启用任何编译器优化,那么答案将是no,原因相同。

答案 3 :(得分:0)

auto在上下文中没有意义,因为您正在处理通用代码,请改用T bar = check;

您未使用的分支机构可能会进行优化(至少是clang / gcc这样做 - 在线查看https://gcc.godbolt.org/),正如其他人在即将推出的C ++ 17中所指出的constexpr if将是您的首选对于这样的编译时任务。

最后通知:由于没有完全了解您的代码,我无法真实地说,但仅从该片段看来,您似乎正在重新发明类型重载或模板专业化。你应该退一步考虑更大的图景。