我正在推动IMO限制C ++模板编程。该系统是Arduino,但我的尝试适用于任何微控制器系统。
我使用带有'int'参数
的模板类来定义Pinstemplate<const int pin>
struct Pin {
Pin() { mode(pin, 0); }
};
template<const int pin>
class PinOut : public Pin<pin> {};
我可以创建模板类来使用PinOut,如:
template<typename F>
class M {
public:
M() { }
F mF;
};
M<PinOut<1>> m1;
template<int F>
class N {
public:
N() { }
Pin<F> mF;
};
N<1> n1;
但我不想在使用PinOut的类中使用模板。这说明了我的想法,显示了可能的方法,但显然不起作用。
class R {
public:
R(const int i) {
}
PinOut<i> mF; // create template instance here
};
R r1(1); // what I'd like to able to do
我认识到问题是在类R中创建一个类型。
另一种可能性是实例化PinOut变量并将其传入但是再次传递并在类中创建类型是一个问题。像这样:
class S {
public:
S(PinOut<int>& p) { } // how to pass the type and instance
PinOut<p>& mF; // and use it here
};
PinOut<1> pp;
S s1(pp);
对不起,如果这个声音突然,但请不要问为什么或我想要做什么。这是一个实验,我正在推动我对C ++特别是模板的理解。我知道还有其他方法。
答案 0 :(得分:1)
是的,任何采用该类型的函数本身都必须是模板。
但Pin的整个家族是否在不知道T的情况下有些有意义?这可以使用非模板的基类来处理。基类的想法特别方便,因为它可以包含做了解T的虚函数。这使您可以根据需要在编译时和运行时多态之间切换。采取相同的语法#34; Generics&#34;如Java和.NET所示。
更一般地说,这是一种称为类型擦除的概念。您可以搜索该术语以了解更多信息。它被设计到库中,以保持公共代码的通用,并防止通过多个实例的同一段落的无偿乘法。
在你的情况下,pin
是一个非类型参数,这是泛型甚至不做的事情。但它可能根本不会真正影响类型:成员的变化取决于pin
?这可能是一个数组绑定,或者是用于提供编译时知识和优化的编译时常量,或者仅用于使类型不同。
所有这些案例都可以在运行时处理。如果它的唯一目的是使类型不同(例如,让编译器检查您将时间值和距离值传递给正确的参数)那么真正的内容是 all 在一个基础中忽略了独特性的课程。
如果它是一个数组绑定或其他类型的差异,可以在运行时进行管理,那么基类或适配器/代理可以在运行时进行。更一般地说,一个不会影响类布局的编译时常量可以在运行时以相同的效果知道,只需要更少的优化。
从您的示例中,使引脚成为构造函数参数是明智的,类可以以正常方式使用运行时配置实现。为什么它是模板?据推测,对于编译时检查,将单独的事物分开。这并不会导致它们以不同的方式工作,因此您希望编译时部分是可选的。因此,这是一个基类可以解决问题的情况:
class AnyPin
{
public:
AnyPin (int pin); // run-time configuration
};
template <int pin>
class Pin : public AnyPin { ⋯ };
现在您可以编写采用AnyPin的函数,或编写采用Pin&lt; 5&gt;的函数。并获得编译时检查。
那么pin
在类的布局和功能方面做了什么呢?是否有任何使得将其作为运行时构造函数值实现的不可接受的事情?
您要求我们不要询问您尝试做什么,但我必须说模板具有某些功能和优点,并且必须有一些理由将其作为模板。简单地说以语言为中心的术语,我是否因为上述分析而错过了什么?如果我的摘要没有涵盖它,你能否给出C ++编程的理由,希望它成为一个模板?这可能就是为什么到目前为止你没有得到任何答案。