假设我有很多音频效果到一个枚举:
enum AudioEffect {
CHORUS,
FILTER,
GAIN,
OSCILATOR,
PHASER
};对于每个类,都有一个类指定如何处理音频字节:
class ChorusProcessor : public ProcessorBase
{
public:
ChorusProcessor()
{
}
}
class FilterProcessor : public ProcessorBase
{
public:
FilterProcessor()
{
}
}每个处理器类都有可以更改的参数,这些参数是音频控制器(静音/非静音、滑块等)。
如果不制作处理器实例,是否可以遍历枚举,并为每个枚举获取具有最小值和最大值的可控值列表?
我认为C++足够聪明,可以让我们做这些事情。我开始思考如何将Chorus与ChorusProcessor、Filter与FilterProcessor等联系起来。
然后,我会让所有处理器类派生自一个类,比如AudioEffectDescription,它有一些描述每个参数的constexpr。
发布于 2021-05-20 22:03:28
你可以用一些诡计来做这件事,但我不确定它到底有多有用。您必须面对的主要问题是,一般情况下,您的enum.不能轻松地迭代的所有值。由于普通enum的底层数据类型是整数,所以可以使用enum,但是对于手动设置值的任何enum,都会失败,例如
enum class AudioEffect {
Chorus = 3,
Filter = 6,
Gain = 5,
Oscillator = 2,
Phaser = 1
};通常,您必须创建一个额外的数据结构,如std::tuple或std::vector<AudioEffect>,添加所有可能的值并使用类似于可变模板的东西循环(一旦使用模板参数,普通循环就不够用了)。此外,在virtual static中,C++中没有、、、functions、这样的东西。
专业模板类
我想出的最好办法是:
template <AudioEffect E> class Processor,专门为所有可能的模板参数指定。我添加了两个static constexpr函数来获取min和max。必须在所有专门化中宣布这一点。我使用了两个函数min和max,它们返回一个最小值和一个最大值,但是您可以返回一个包含有关不同限制的更多信息的std::string_view (或者在C++20中可以返回一个constexpr std::string)。
模板类处理器: ProcessorBase { };模板<>类Processor:ProcessorBase { public: //或用于打印该类的所有设置的单个函数--静态参数int min() {返回1;template class Preprocessor的每个实例都有一个static constexpr函数min和另一个max )
模板 std::string print() {std::<< << "\t min:“<< Processor::min() << ",\t max:”<< Processor::max() << std::endl),.);返回ss.str()};地图
另一种类似的方法是将enum映射到classes (不再需要专门化的模板)和traits (如这里 by )。
enum值和classes之间映射的enum。
模板结构映射;template<>结构Map {使用类型= ChorusProcessor;};这与使用意见中提出的解决办法的std::tuple非常相似。
using Processors = std::tuple<
ChorusProcessor,
FilterProcessor,
GainProcessor,
OscilatorProcessor,
PhaserProcessor
>;
std::tuple_element_t<AudioEffect::Filter, Processors>::value简约但肮脏的
如果您使用enum而没有显式地指定值,您也可以使用一个脏的解决方案,只提供enum (C++17)的第一个和最后一个值。
template <AudioEffect Begin, AudioEffect End>
std::string print() {
std::stringstream ss;
ss << Begin << "\t min: " << Processor<Begin>::min() << ",\t max: " << Processor<Begin>::max() << std::endl;
if constexpr (Begin != End) {
ss << print<static_cast<AudioEffect>(static_cast<int>(Begin)+1), End>();
}
return ss.str();
}这样,您就可以先用enum的值和的最后一个值调用它。
std::cout << print<AudioEffect::Chorus,AudioEffect::Phaser>() << std::endl;Enum反射
最后,利用GCC、Clang和MSVC编译器,提出了一种用__PRETTY_FUNCTION__ identifier (描述为的这里 )获取某些枚举属性的方法。(在原始代码中有一些输入,但它不是constexpr,所以最好尝试一下这里。)使用它,您可以通过从0 循环到检测到的 enum 值的循环,完全消除Begin和End。这有点复杂,所以我只留下代码给你试试看。使用它,您可以输出所有类,而无需显式地指定所有enum值:
std::cout << print<AudioEffect>() << std::endl;https://stackoverflow.com/questions/67627762
复制相似问题