我想为ARM 32位微控制器编写,我想使用现代C ++进行教育。我的目标是:可读代码,可在编译时配置,并帮助编译器生成大小和速度的最大优化。我应该使用哪些语言工具来归档我的目标? 我写了一些代码,静态断言不起作用...请帮我修复这段代码(添加断言,没有开销)。
#include <initializer_list>
#include <vector>
typedef uint port_type;
typedef uint pin_type;
class Pin {
private:
const port_type _port;
const pin_type _pin;
public:
Pin(const port_type port, const pin_type pin) :
_port(port), _pin(pin) {
}
};
class Actuator {
private:
const Pin _enable_pin;
const Pin _dir_pin;
const Pin _step_pin;
public:
Actuator(const Pin enable_pin, const Pin dir_pin, const Pin step_pin) :
_enable_pin(enable_pin), _dir_pin(dir_pin), _step_pin(step_pin) {
}
};
class Machine {
private:
const std::vector<Actuator> _actuators;
public:
Machine(const std::initializer_list<Actuator> actuators) :
_actuators(actuators) {
/*check: all actuators _enable_pin ports are same*/
/*check: all actuators _dir_pin ports are same*/
/*check: all actuators _step_pin ports are same*/
/*check: all port/pin pairs are unique*/
}
};
int main() {
/*example: good sequence*/
Actuator act1(Pin(1, 1), Pin(1, 2), Pin(1, 3));
Actuator act2(Pin(1, 4), Pin(1, 5), Pin(1, 6));
Machine machine1( { act1, act2 });
/*example: bad sequence*/
Actuator act3(Pin(2, 1), Pin(2, 2), Pin(2, 2)); // NOK! Pin(2,2) already used!
Actuator act4(Pin(2, 1), Pin(2, 3), Pin(2, 4)); // NOK! Pin(2,1) already used in act3!
Machine machine2( { act3, act4 });
}
答案 0 :(得分:3)
使用大量constexpr
,std::array
代替std::vector
并将Machine
定义为模板类(其参数是std::array
的维度) ,您可以在Machine
方法中转换constexpr
的构造函数,该方法在运行时抛出异常,或者在对象Machine
定义为constexpr
时,编译时。
以下示例(遗憾的是C ++ 14但不是C ++ 11)拦截编译时,Pin
中有两个等于act3
#include <array>
#include <stdexcept>
#include <initializer_list>
typedef std::size_t port_type;
typedef std::size_t pin_type;
class Pin
{
private:
port_type const _port;
pin_type const _pin;
public:
constexpr Pin (port_type const port, pin_type const pin)
: _port{port}, _pin{pin}
{ }
friend constexpr bool operator== (Pin const & p1, Pin const & p2)
{ return (p1._port == p2._port) && (p1._pin == p2._pin); }
};
class Actuator
{
private:
Pin const _enable_pin;
Pin const _dir_pin;
Pin const _step_pin;
public:
constexpr Actuator (Pin const ep, Pin const dp, Pin const sp)
: _enable_pin{ep}, _dir_pin{dp}, _step_pin{sp}
{ }
constexpr bool checkColl () const
{ return (_enable_pin == _dir_pin) || (_enable_pin == _step_pin)
|| (_dir_pin == _step_pin); }
};
template <std::size_t N>
class Machine
{
private:
std::array<Actuator, N> const _actuators;
public:
template <typename ... Args>
constexpr Machine (Args const & ... actuators)
: _actuators{ { actuators ... } }
{
static_assert(sizeof...(Args) == N, "!");
for ( auto ui = 0U ; ui < N ; ++ui )
{
if ( _actuators[ui].checkColl() )
throw std::logic_error("port collision");
// other checks here
}
}
};
int main()
{
constexpr Actuator act1 { Pin{ 1, 1 }, Pin{ 1, 2 }, Pin{ 1, 3 } };
constexpr Actuator act2 { Pin{ 1, 4 }, Pin{ 1, 5 }, Pin{ 1, 6 } };
constexpr Machine<2U> machine1 { act1, act2 };
constexpr Actuator act3 { Pin{ 2, 1 }, Pin{ 2, 2 }, Pin{ 2, 2 } };
constexpr Actuator act4 { Pin{ 2, 1 }, Pin{ 2, 3 }, Pin{ 2, 4 } };
constexpr Machine<2U> machine2 { act3, act4 }; // compilation error
}
您可以添加其他支票。
答案 1 :(得分:1)
OP说
我的课程中需要非const成员。例如,我需要将max_velocity参数添加到Actuator类中,当然我需要在运行时更改此参数,但引脚必须始终为const。我怎样才能做到这一点(在运行时最好的表现)?
我不是最佳性能(运行时或编译时)的专家,但是,如果你需要检查编译时间而不应该在运行时修改对象......最好我能想到你可以试试的方法是将const元素作为类型进行管理。
所以我建议你另一个基于Pin<std::size_t, std::size_t>
模板结构的完全不同的例子。
希望这有帮助
#include <vector>
#include <iostream>
template <typename, typename>
struct PairIsEq : std::false_type
{ };
template <template <std::size_t, std::size_t> class C,
std::size_t S1, std::size_t S2>
struct PairIsEq<C<S1, S2>, C<S1, S2>> : std::true_type
{ };
template <std::size_t O, std::size_t I>
struct Pin
{ };
template <typename, typename, typename, typename = void>
struct Actuator0;
template <typename EnableP, typename DirP, typename StepP>
struct Actuator0<EnableP, DirP, StepP,
typename std::enable_if< (false == PairIsEq<EnableP, DirP>::value)
&& (false == PairIsEq<EnableP, StepP>::value)
&& (false == PairIsEq<DirP, StepP>::value)>::type>
{
// something modifiable
std::size_t max_vel = 0U;
};
struct ActBase
{ };
template <typename P1, typename P2, typename P3,
bool = PairIsEq<P1, P2>::value
|| PairIsEq<P1, P3>::value
|| PairIsEq<P2, P3>::value>
struct Actuator;
template <typename EnableP, typename DirP, typename StepP>
struct Actuator<EnableP, DirP, StepP, false> : public ActBase
{
// something modifiable
std::size_t max_vel = 0U;
};
template <typename, typename>
struct CheckA : public std::false_type
{ };
template <typename P1a, typename P2a, typename P3a,
typename P1b, typename P2b, typename P3b>
struct CheckA<Actuator<P1a, P2a, P3a>, Actuator<P1b, P2b, P3b>>
: public std::integral_constant<bool,
(false == PairIsEq<P1a, P1b>::value)
&& (false == PairIsEq<P2a, P2b>::value)
&& (false == PairIsEq<P3a, P3b>::value)>
{ };
template <bool, typename ...>
struct CheckActs
{ };
template <typename Act0>
struct CheckActs<true, Act0>
{ using type = void; };
template <typename Act0, typename Act1, typename ... Acts>
struct CheckActs<true, Act0, Act1, Acts...>
: public CheckActs<CheckA<Act0, Act1>::value, Act0, Acts...>
{ };
struct Machine
{
std::vector<ActBase> const _actuators;
template <typename ... Acts,
typename CheckActs<true, Acts...>::type * = nullptr>
Machine (Acts const & ... acts) : _actuators{ acts... }
{ }
};
int main ()
{
// act1 compile (all Pins are different) ...
Actuator<Pin<1U, 1U>, Pin<1U, 2U>, Pin<1U, 3U>> act1;
// ...and is modifiable
act1.max_vel = 1U;
// act2 compile (all Pins are different)
Actuator<Pin<1U, 4U>, Pin<1U, 5U>, Pin<1U, 6U>> act2;
// act3 doesn't compile: EnableP and StepP are equals
//Actuator<Pin<2U, 1U>, Pin<2U, 2U>, Pin<2U, 2U>> act3;
// act4 compile (all Pin are different)
Actuator<Pin<2U, 1U>, Pin<2U, 3U>, Pin<2U, 4U>> act4;
// act5 compile (all Pin are different)
Actuator<Pin<2U, 1U>, Pin<2U, 4U>, Pin<2U, 5U>> act5;
// mac1 compile: no Pin collisions
Machine mac1 { act1, act2, act4 };
// mac2 compilation error: EnablePin collision
// Machine mac2 { act4, act5 };
}