避免基于作为模板参数的函数的返回值的分支 [英] Avoiding branching based on the return value of the function that is a template argument

查看:106
本文介绍了避免基于作为模板参数的函数的返回值的分支的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设以下策略类照顾算法的一个方面:

  struct VoidF {
static void f(){
... //有副作用的代码
}
};

struct BoolF {
static bool f(){
bool res = ...; //一些计算
return res;
}
};

BoolF 政策是 :当BoolF :: f()返回 true 时,算法可以退出。 VoidF 是增强 - 不知道,因此它返回 void (我不想强迫用户的

该算法目前是这样编写的: bool

 模板< typename F> 
struct算法{
void run(){
... //这里的计算

if(std :: is_same if(F :: f())return;
} else
F :: f(); //如果F是VoidF,应该没有分支和
//编译器优化将被启用

... //更多的计算,除非F :: f()摆脱of it
}
};

当然,如果 Algorithm VoidF 实例化。有没有办法解决这个问题,应该没有分支在算法< VoidF> :: run()如注释所示?

解决方案

您应该在运行时使用SFINAE而不是分支。



你的函数运行应该看起来像这样:

  template< typename F> 
struct算法{

void run(){
... //这里的一些计算

doRun();
}

template< std :: enable_if_t< std :: is_same< decltype(F :: f()),bool> :: value,int& = 0>
void doRun(){
if(F :: f()){
//如果需要,做更多的计算,或者简单地删除if和返回
}
}

template< std :: enable_if_t<!std :: is_same< decltype(F :: f()),bool> :: value,int& = 0>
void doRun(){
F :: f();

... //更多的计算,除非F :: f()摆脱它
}
};


Suppose the following policy classes that take care of one aspect of an algorithm:

struct VoidF {
    static void f() {
        ... // some code that has side effects
    }
};

struct BoolF {
    static bool f() {
        bool res = ...; // some computation
        return res;
    }
};

The BoolF policy is "enhancement-aware": when BoolF::f() returns true, the algorithm can exit. VoidF is "enhancement-unaware", hence it returns void (I don't want to force the user of my library to return bool when it does not mean anything to him).

The algorithm is currently written like this:

template <typename F>
struct Algorithm {
    void run() {
        ... // some computation here

        if (std::is_same<decltype(F::f()), bool>::value) {
            if (F::f()) return;
        } else
            F::f(); // If F is VoidF, there should be no branching and some
                    // compiler optimizations will be enabled

        ... // more computation, unless F::f() got rid of it
    }
};

Of course, this does not work if Algorithm is instantiated with VoidF. Is there a way to fix this in a way that there should be no branching in Algorithm<VoidF>::run() as indicated by the comment?

解决方案

You should use SFINAE instead of branching at runtime.

You function run should look like this:

template <typename F>
struct Algorithm {

    void run() {
        ... // some computation here

        doRun();
    }

    template<std::enable_if_t<std::is_same<decltype(F::f()), bool>::value, int> = 0>
    void doRun() {
        if (F::f()) {
            // do some more computations if needed or simply remove the if and return
        }
    }

    template<std::enable_if_t<!std::is_same<decltype(F::f()), bool>::value, int> = 0>
    void doRun() {
        F::f();

        ... // more computation, unless F::f() got rid of it
    }
};

这篇关于避免基于作为模板参数的函数的返回值的分支的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆