WPILibC++  2020.3.2
SelectCommand.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2019 FIRST. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in the root directory of */
5 /* the project. */
6 /*----------------------------------------------------------------------------*/
7 
8 #pragma once
9 
10 #ifdef _WIN32
11 #pragma warning(push)
12 #pragma warning(disable : 4521)
13 #endif
14 
15 #include <memory>
16 #include <type_traits>
17 #include <unordered_map>
18 #include <utility>
19 #include <vector>
20 
21 #include "frc2/command/CommandBase.h"
22 #include "frc2/command/CommandGroupBase.h"
23 #include "frc2/command/PrintCommand.h"
24 
25 namespace frc2 {
42 template <typename Key>
43 class SelectCommand : public CommandHelper<CommandBase, SelectCommand<Key>> {
44  public:
51  template <class... Types,
52  typename = std::enable_if_t<std::conjunction_v<
53  std::is_base_of<Command, std::remove_reference_t<Types>>...>>>
54  SelectCommand(std::function<Key()> selector,
55  std::pair<Key, Types>... commands)
56  : m_selector{std::move(selector)} {
57  std::vector<std::pair<Key, std::unique_ptr<Command>>> foo;
58 
59  ((void)foo.emplace_back(commands.first,
60  std::make_unique<std::remove_reference_t<Types>>(
61  std::move(commands.second))),
62  ...);
63 
64  for (auto&& command : foo) {
65  if (!CommandGroupBase::RequireUngrouped(command.second)) {
66  return;
67  }
68  }
69 
70  for (auto&& command : foo) {
71  this->AddRequirements(command.second->GetRequirements());
72  m_runsWhenDisabled &= command.second->RunsWhenDisabled();
73  m_commands.emplace(std::move(command.first), std::move(command.second));
74  }
75  }
76 
78  std::function<Key()> selector,
79  std::vector<std::pair<Key, std::unique_ptr<Command>>>&& commands)
80  : m_selector{std::move(selector)} {
81  for (auto&& command : commands) {
82  if (!CommandGroupBase::RequireUngrouped(command.second)) {
83  return;
84  }
85  }
86 
87  for (auto&& command : commands) {
88  this->AddRequirements(command.second->GetRequirements());
89  m_runsWhenDisabled &= command.second->RunsWhenDisabled();
90  m_commands.emplace(std::move(command.first), std::move(command.second));
91  }
92  }
93 
94  // No copy constructors for command groups
95  SelectCommand(const SelectCommand& other) = delete;
96 
97  // Prevent template expansion from emulating copy ctor
98  SelectCommand(SelectCommand&) = delete;
99 
105  explicit SelectCommand(std::function<Command*()> toRun) : m_toRun{toRun} {}
106 
107  SelectCommand(SelectCommand&& other) = default;
108 
109  void Initialize() override;
110 
111  void Execute() override { m_selectedCommand->Execute(); }
112 
113  void End(bool interrupted) override {
114  return m_selectedCommand->End(interrupted);
115  }
116 
117  bool IsFinished() override { return m_selectedCommand->IsFinished(); }
118 
119  bool RunsWhenDisabled() const override { return m_runsWhenDisabled; }
120 
121  protected:
122  std::unique_ptr<Command> TransferOwnership() && override {
123  return std::make_unique<SelectCommand>(std::move(*this));
124  }
125 
126  private:
127  std::unordered_map<Key, std::unique_ptr<Command>> m_commands;
128  std::function<Key()> m_selector;
129  std::function<Command*()> m_toRun;
130  Command* m_selectedCommand;
131  bool m_runsWhenDisabled = true;
132 };
133 
134 template <typename T>
136  if (m_selector) {
137  auto find = m_commands.find(m_selector());
138  if (find == m_commands.end()) {
139  m_selectedCommand = new PrintCommand(
140  "SelectCommand selector value does not correspond to any command!");
141  return;
142  }
143  m_selectedCommand = find->second.get();
144  } else {
145  m_selectedCommand = m_toRun();
146  }
147  m_selectedCommand->Initialize();
148 }
149 
150 } // namespace frc2
151 
152 #ifdef _WIN32
153 #pragma warning(pop)
154 #endif
frc2::SelectCommand::TransferOwnership
std::unique_ptr< Command > TransferOwnership() &&override
Transfers ownership of this command to a unique pointer.
Definition: SelectCommand.h:122
frc2::Command::IsFinished
virtual bool IsFinished()
Whether the command has finished.
Definition: Command.h:88
frc2::SelectCommand::SelectCommand
SelectCommand(std::function< Key()> selector, std::pair< Key, Types >... commands)
Creates a new selectcommand.
Definition: SelectCommand.h:54
frc2::SelectCommand::SelectCommand
SelectCommand(std::function< Command *()> toRun)
Creates a new selectcommand.
Definition: SelectCommand.h:105
frc2::Command::Execute
virtual void Execute()
The main body of a command.
frc2::Command::End
virtual void End(bool interrupted)
The action to take when the command ends.
frc2::SelectCommand::IsFinished
bool IsFinished() override
Whether the command has finished.
Definition: SelectCommand.h:117
frc2::CommandGroupBase::RequireUngrouped
static bool RequireUngrouped(Command &command)
Requires that the specified command not have been already allocated to a CommandGroup.
frc2::SelectCommand::Execute
void Execute() override
The main body of a command.
Definition: SelectCommand.h:111
frc2::SelectCommand
Runs one of a selection of commands, either using a selector and a key to command mapping,...
Definition: SelectCommand.h:43
frc2::SelectCommand::End
void End(bool interrupted) override
The action to take when the command ends.
Definition: SelectCommand.h:113
frc2::Command
A state machine representing a complete action to be performed by the robot.
Definition: Command.h:52
frc2::SelectCommand::RunsWhenDisabled
bool RunsWhenDisabled() const override
Whether the given command should run when the robot is disabled.
Definition: SelectCommand.h:119
frc2::CommandBase::AddRequirements
void AddRequirements(std::initializer_list< Subsystem * > requirements)
Adds the specified requirements to the command.
frc2::CommandHelper
CRTP implementation to allow polymorphic decorator functions in Command.
Definition: CommandHelper.h:26
frc2::SelectCommand::Initialize
void Initialize() override
The initial subroutine of a command.
Definition: SelectCommand.h:135
frc2::PrintCommand
A command that prints a string when initialized.
Definition: PrintCommand.h:19