【发布时间】:2020-06-14 19:09:56
【问题描述】:
这目前是伪代码,因为这是我在开始将其编写为完整代码之前正在研究的一个想法。
我知道我可以创建一个使用va_arg 和va_list 的普通可变参数函数,例如printf(),但是我想完全避免使用它们。
我正在考虑改用模板化可变参数。我正在考虑使用可变参数制作一个可实例化的类模板。这里的条件是这个类的构造函数只能接受两种类型,但任何一种类型的数量都可以变化。我知道与编译器将如何解释以及调用它们的顺序相比,参数在代码中的写入位置是不可知的,但这不是问题。我为参数选择的顺序是出于可读性和一致性目的的约定。
这是一个伪代码示例:
class TypeIn {...}
class TypeOut{...}
template<typename... T1, typename... T2>
class MyObject {
std::array<TypeIn*> inputs_;
std::array<TypeOut*> outputs_;
public:
MyObject(T1&&... inputs, T2&& ... outputs) { ... }
};
由于我仍在使用 C++17 并且还没有 C++20 的概念、模块和协程,那么确保T1是TypeIn 和T2 是TypeOut 类对象并相应地填充数组?我可以使用向量,但是一旦构造了对象,输入和输出的大小就不会改变。
可能的用例是:
using In = TypeIn;
using Out = TypeOut;
MyObject obj( In a, In b, In c, Out x, Out y);
如果可能的话,我宁愿不使用这个语法:
MyObject<In,In,In,Out,Out> obj( In a, In b, In c, Out X, Out y);
因为第一个更清晰或更易读。
编辑
经过一番思考后,我想知道这是否可行……
class In {...}
class Out{...}
// template<typename T1 = In, typename T2 = Out>
// T1 must == type In and T2 must == type Out
class MyObject {
private:
std::vector<In*> inputs_;
std::vector<Out*> outputs_;
public:
MyObject() = deafault;
template<typename... Inputs> // would probably use move semantics or forwarding
void assignInputs(Inputs&& ... inputs);
template<typename... Outputs> // would probably use move semantics or forwarding
void assignOutputs(Inputs&& ... outputs);
};
但是,这将迫使用户必须构造对象,然后调用这两个函数......我试图在构造时完成所有这些......
【问题讨论】:
-
有许多可能的方法,基于 SFINAE 或 static_asserts。哪种方法更适合您?
-
@SamVarshavchik 我明白这一点,但这就是我被困在决策树上的地方......所以很高兴看到一些不同方法的例子,然后我可以根据我的决定从那里采取哪条路线......
-
你真的希望你的构造函数只接受右值引用吗? (仅当函数本身是模板时才会发生转发引用)
-
MyObject(std::array<In, N1> inputs, std::array<Out, N2> outputs)有什么问题? -
@FrancisCugler 那仍然是在编译时。不过,您需要将元素保存在
std::vectors中。除了将std::array更改为std::vector之外,Jarod42 的建议仍然有效。
标签: c++ types c++17 variadic-templates pack-expansion