Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 递归变量函数调用对简单if..else语句的性能_C++_C++11_C++17_Variadic Templates_Variadic Functions - Fatal编程技术网

C++ 递归变量函数调用对简单if..else语句的性能

C++ 递归变量函数调用对简单if..else语句的性能,c++,c++11,c++17,variadic-templates,variadic-functions,C++,C++11,C++17,Variadic Templates,Variadic Functions,我希望这个主题反映了我想问的问题。。。我尽了最大的努力 我们必须根据几个运行时条件设置某些变量。我们总是使用if..else语句,但我发现它们太麻烦了,特别是考虑到可能有几个条件。我尝试使用c++11/17特性开发一些东西,并得出以下结论 因此,我的问题是:性能和可读性,您愿意使用以下选项吗 template <typename DST, typename... Ts> void SetValue(DST& dst, Ts&&... ts) { Check

我希望这个主题反映了我想问的问题。。。我尽了最大的努力

我们必须根据几个运行时条件设置某些变量。我们总是使用if..else语句,但我发现它们太麻烦了,特别是考虑到可能有几个条件。我尝试使用c++11/17特性开发一些东西,并得出以下结论

因此,我的问题是:性能和可读性,您愿意使用以下选项吗

template <typename DST, typename... Ts>
void SetValue(DST& dst, Ts&&... ts)
{
  CheckAndSetVal(dst, std::forward<Ts>(ts)...);
}

template <typename DST>
void CheckAndSetVal(DST&) {}

template <typename DST, typename T1, typename T2, typename... Ts>
std::enable_if_t<std::is_same_v<DST, T2> > CheckAndSetVal(DST& dst, T1&& cond, T2&& val, Ts&&... ts)
{
  if (cond())
    dst = val; // Assign the value here ...
  else
    CheckAndSetVal(dst, std::forward<Ts>(ts)...);
}

template <typename DST, typename T1, typename T2, typename... Ts>
std::enable_if_t<!std::is_same_v<DST, T2> > CheckAndSetVal(DST& dst, T1&& cond, T2&& val, Ts&&... ts)
{
  if (cond())
    dst = val(); // Assign the value using this functor .. 
  else
    CheckAndSetVal(dst, std::forward<Ts>(ts)...);
}

  int i;
  //
  // In practive though the conditions are not as trivial as they look here. 
  //
  SetValue(i, []() { return false; }, 444
            , []() { return false; }, 999
            , []() { return true; }, []() { return 222; });
模板
无效设置值(DST和DST、Ts和…Ts)
{
CheckAndSetVal(dst、std::forward(ts)…);
}
模板
void CheckAndSetVal(DST&){}
模板
std::启用检查和设置值(DST&DST、T1&cond、T2&val、Ts&;Ts)
{
if(cond())
dst=val;//在此处赋值。。。
其他的
CheckAndSetVal(dst、std::forward(ts)…);
}
模板
std::如果>CheckAndSetVal(DST&DST、T1&cond、T2&val、Ts&val)则启用
{
if(cond())
dst=val();//使用此函子赋值。。
其他的
CheckAndSetVal(dst、std::forward(ts)…);
}
int i;
//
//在实践中,虽然条件并不像这里看起来的那么简单。
//
SetValue(i,[](){return false;},444
,[](){返回false;},999
,[](){return true;},[](){return 222;});

如果该函数的可读性是一个问题,那么您可以使用C++17:)摆脱很多SFINAE魔法

#包括
#包括
模板
无效设置值(目标和输出、条件和条件、值和值、Ts和…Ts)
{
if(cond())
{
如果constexpr(std::is\u invocable\u v)
{
out=value();
}
其他的
{
out=值;
}
}
其他的
{
如果constexpr(sizeof…(Ts)!=0)
{
设置值(输出,标准::正向(ts)…);
}
}
}
int main()
{
int i;
SetValue(i,[](){return false;},444,
[](){返回false;},999,
[](){return true;},[](){return 222;});
返回i;
}
对于发布版本,性能应该完全相同,对于未优化的版本,性能可能会稍慢一些。例如,上面的代码在gcc/clang上编译为
return222
,并进行了优化。不过,编译时可能需要一些时间


我不喜欢这种巨大的可变函数调用,但有时它们是值得的,因为它们在整个代码库中节省了大量输入。在不了解实际用例的情况下,很难说清楚。

如果该函数的可读性是一个问题,那么您可以使用C++17:)摆脱很多SFINAE魔法

#包括
#包括
模板
无效设置值(目标和输出、条件和条件、值和值、Ts和…Ts)
{
if(cond())
{
如果constexpr(std::is\u invocable\u v)
{
out=value();
}
其他的
{
out=值;
}
}
其他的
{
如果constexpr(sizeof…(Ts)!=0)
{
设置值(输出,标准::正向(ts)…);
}
}
}
int main()
{
int i;
SetValue(i,[](){return false;},444,
[](){返回false;},999,
[](){return true;},[](){return 222;});
返回i;
}
对于发布版本,性能应该完全相同,对于未优化的版本,性能可能会稍慢一些。例如,上面的代码在gcc/clang上编译为
return222
,并进行了优化。不过,编译时可能需要一些时间


我不喜欢这种巨大的可变函数调用,但有时它们是值得的,因为它们在整个代码库中节省了大量输入。如果不知道您的实际用例,很难判断。

老实说,我更喜欢
if else
语句或
?:
操作符。 易于调试或解释崩溃转储。 非C++开发人员或初学者更容易阅读。
而且没有明显的缺点。

老实说,我更喜欢
if-else
语句或
?:
操作符。 易于调试或解释崩溃转储。 非C++开发人员或初学者更容易阅读。
而且没有明显的缺点。

谢谢您的快速回复。首先,我很惊讶这会编译,因为作为可调用函数和值的用法似乎在同一个函数中。这是否意味着只有if..else部分中的一个被编译成了目标代码?如果不是,那么“out=value()”和“out=value”怎么可能在同一个函数中?@lightsunray:对于常规的
If
,这将是有问题的,但是我们在这里使用
If constexpr
,它“丢弃”了错误的分支。@Asu:这也清楚地表明
out
可能保持不变(因此无法在函数中按原样返回它)@Asu:谢谢。有“if constexpr”的那个对我来说是全新的。谢谢你的快速回复。首先,我很惊讶这会编译,因为作为可调用函数和值的用法似乎在同一个函数中。这是否意味着只有if..else部分中的一个被编译成了目标代码?如果不是,那么“out=value()”和“out=value”怎么可能在同一个函数中?@lightsunray:对于常规的
If
,这将是有问题的,但是我们在这里使用
If constexpr
,它“丢弃”了错误的分支。@Asu:这也清楚地表明
out
可能保持不变(因此无法在函数中按原样返回它)@Asu:谢谢。带有“if constexpr”的那个对我来说是全新的。为了可读性,我可能会将
{cond,val}
分组到它自己的类中,一个“lazyOptional”。对于C++11,它意味着使用类似于
std::pairforreadability的
std::function
,我可能会将
{cond,val}
分组到它自己的类中,一个“lazyOptional”。在C++11中,它意味着使用
std::function
std::pairw之类的东西。在可读性方面,简单的if..else对于单个变量来说是不可替代的。但在我的用例中,我有se
#include <functional>
#include <type_traits>

template<class DestT, class CondT, class ValueT, class... Ts>
void SetValue(DestT& out, CondT&& cond, ValueT&& value, Ts&&... ts)
{
    if (cond())
    {
        if constexpr (std::is_invocable_v<ValueT>)
        {
            out = value();
        }
        else
        {
            out = value;
        }
    }
    else
    {
        if constexpr (sizeof...(Ts) != 0)
        {
            SetValue(out, std::forward<Ts>(ts)...);
        }
    }
}

int main()
{
    int i;
    SetValue(i, []() { return false; }, 444,
                []() { return false; }, 999,
                []() { return true; }, []() { return 222; });

    return i;
}