C++ 在C+中组织涉及有限范围的常量引用和模板的代码的好方法+;
因此,我有以下代码:C++ 在C+中组织涉及有限范围的常量引用和模板的代码的好方法+;,c++,c++11,templates,reference,auto,c++14,c++17,c++03,C++,C++11,Templates,Reference,Auto,C++14,C++17,C++03,因此,我有以下代码: if (some_boolean_statement) { const auto& ref = getRef<TYPE_A>(); //getRef returns TYPE_A doStuff(ref); } else { const auto& ref = getRef<TYPE_B>(); //getRef returns TYPE_B doStuff(ref); } if(一些布尔语句) {
if (some_boolean_statement)
{
const auto& ref = getRef<TYPE_A>(); //getRef returns TYPE_A
doStuff(ref);
}
else
{
const auto& ref = getRef<TYPE_B>(); //getRef returns TYPE_B
doStuff(ref);
}
if(一些布尔语句)
{
const auto&ref=getRef();//getRef返回类型A
多斯塔夫(参考);
}
其他的
{
const auto&ref=getRef();//getRef返回类型
多斯塔夫(参考);
}
因此,我想获得一个常量引用ref
,它取决于某个布尔语句为true
或false
是类型a
或类型B
。
之后,不管怎样,我都将调用一个重载函数doStuff()
,该函数可以接受这两种类型作为输入
注:
getRef()
和getRef()
是在不同的数据上操作的,它们几乎是不相关的
某些布尔语句是运行时的
现在,我不喜欢我必须写doStuff(ref)。但是由于ref
的范围有限,我看不到一个明确的方法来实现它
我错过了一些非常简单的东西吗?有什么建议吗?由于在运行时对某个布尔语句进行了计算,因此无法避免代码中的if-else
部分
如果语句的每个分支中必须包含的最少代码量是一条语句。最好是编写其他函数或函数模板,以尽量减少两个分支中的代码量
你可以用
if (some_boolean_statement)
{
doStuff<TYPE_A>();
}
else
{
doStuff<TYPE_B>();
}
if(一些布尔语句)
{
doStuff();
}
其他的
{
doStuff();
}
在哪里
template <typename T> void doStuff()
{
doStuff(getRef<T>());
}
模板void doStuff()
{
doStuff(getRef());
}
我看不出你还能做得比这更好。此外,如果这是您的代码中最大的问题,那么您的代码的状态很好。将控制流和运行时转换为编译时调度器
这是疯狂的复杂,和适度复杂的
在中,您可以获得:
pick( some_boolean_statement,
&getRef<TYPE_A>,
&getRef<TYPE_B>
)([&](auto* getRef){
const auto& ref = getRef();
doStuff(ref);
});
可以编写类似于交换机的dispatcher类,该类将条件值映射到目标类型,并接受只执行一次的操作,因此用法类似于:
Switch<Action, bool, Case<true, TYPE_A>, Case<false, TYPE_B>>(some_boolean_statement);
Switch第一次调用的类型与第二次调用的类型之间是否存在任何关系?@raket1111getRef
是一个模板函数,它将溢出类型a
或类型B
的对象。根据不同的情况,它将执行非常不同的不相关的操作。@Jarod42不幸的是,没有。那么这段代码有什么不好的地方呢?如果两个分支都在不同的类型上运行并执行不同的任务,那么我看不出有什么问题。键入doStuff
两次似乎不是构建某些模板(调用这些模板可能需要大约相同的键入量)的充分理由。删除ref
变量:)if(cond){doStuff(getRef());}else{doStuff(getRef());}
?
Switch<Action, bool, Case<true, TYPE_A>, Case<false, TYPE_B>>(some_boolean_statement);
#include <iostream>
#include <cstdlib>
template<auto cond, typename x_Target> struct
Case;
template<template<typename T> class x_Action, typename x_Cond, typename... x_Case>
class DispatchImpl;
template<template<typename T> class x_Action, typename x_Cond, x_Cond this_cond, typename x_Target, typename... x_Case>
class DispatchImpl<x_Action, x_Cond, Case<this_cond, x_Target>, x_Case...>
{
public: static void Dispatch(x_Cond cond)
{
if(this_cond == cond)
{
x_Action<x_Target>::Invoke();
}
else
{
DispatchImpl<x_Action, x_Cond, x_Case...>::Dispatch(cond);
}
}
};
template<template<typename T> class x_Action, typename x_Cond>
class DispatchImpl<x_Action, x_Cond>
{
public: static void Dispatch(x_Cond) {}
};
template<template<typename T> class x_Action, typename x_Cond, typename... x_Case>
void Switch(x_Cond cond)
{
DispatchImpl<x_Action, x_Cond, x_Case...>::Dispatch(cond);
}
//
template<typename T> auto getRef(void) { return T{}; }
void doStuff(int) { ::std::cout << "int" << ::std::endl; }
void doStuff(float) { ::std::cout << "float" << ::std::endl; }
template<typename x_Target> struct
Action
{
static void Invoke(void)
{
doStuff(getRef<x_Target>());
}
};
int main()
{
auto cond{false};
Switch<Action, bool, Case<true, int>, Case<false, float>>(cond);
}