Error to implementation of strategy pattern in C++ - c++

I'm trying to implement the design pattern strategy in C++.
The goal for me is to do an operation on 2 numbers.
Here is my context class
operation::operation(std::unique_ptr<calculatorTask> pTask = nullptr)
{
pCalculatorTask = std::move(pTask);
}
operation::~operation();
{
}
void operation::setTask(std::unique_ptr<calculatorTask> pTask)
{
this->pCalculatorTask = std::move(pTask);
}
void operation::executeTask(numberMsg& sValues)
{
pCalculatorTask->calculate(values);
}
This is my implementation :
int main()
{
std::vector<std::unique_ptr<calculatorTask>> myOperation;
myOperation.push_back(std::move(std::unique_ptr<additionTask>(new additionTask())));
myOperation.push_back(std::move(std::unique_ptr<substractionTask>(new substractionTask())));
for (const auto &Ope : myOperation)
{
pOpe->setTask(Ope);
[...]
}
}
I have this error :
error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = calculatorTask; _Dp = std::default_delete]’
pOpe->setTask(Ope);
I don't understand error and how to fix it.

Related

How to change a container elements in another 'temporary' container

I have a temporary list that needs to change its elements and erase() them from the list as a way of marking them as done.
std::list<Vertex> temp {vertices.begin(), vertices.end()};
I've tried using Vertex& and Vertex* without success, and the second one makes the code very messy.
What is the proper way to do this? Thanks in advance
Edit: surrounding code
int label = 1;
// change elements without affecting temporary list
std::list<Vertex*> unlabeledVertices {graph.vertices.begin(), graph.vertices.end()};
for (auto iter = unlabeledVertices.begin(); iter != unlabeledVertices.end(); ++label) {
(*iter)->label = label;
// temporary list
std::list<Vertex*> currentLabelVertices;
currentLabelVertices.push_back(*iter);
// check if we can label any other vertex with the current color
auto nestedIter = iter;
for (nestedIter++; nestedIter != unlabeledVertices.end(); ) {
// checking current vertex against any other colored vertex
if (std::none_of(currentLabelVertices.begin(), currentLabelVertices.end(),
[=](const Vertex* v){ return (*nestedIter)->isConnected(*v); })) {
(*nestedIter)->label = label;
currentLabelVertices.push_back(*nestedIter);
nestedIter = unlabeledVertices.erase(nestedIter);
}
else {
nestedIter++;
}
}
iter = unlabeledVertices.erase(iter);
}
Error message:
/usr/bin/g++ -fdiagnostics-color=always -g /home/etzl/projects/c-cpp/test/*.cc -o exec
In file included from /usr/include/x86_64-linux-gnu/c++/10/bits/c++allocator.h:33,
from /usr/include/c++/10/bits/allocator.h:46,
from /usr/include/c++/10/string:41,
from /usr/include/c++/10/bits/locale_classes.h:40,
from /usr/include/c++/10/bits/ios_base.h:41,
from /usr/include/c++/10/ios:42,
from /usr/include/c++/10/ostream:38,
from /usr/include/c++/10/iostream:39,
from /home/etzl/projects/c-cpp/test/main.cc:1:
/usr/include/c++/10/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Vertex*; _Args = {Vertex&}; _Tp = std::_List_node<Vertex*>]’:
/usr/include/c++/10/bits/alloc_traits.h:512:17: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = Vertex*; _Args = {Vertex&}; _Tp = std::_List_node<Vertex*>; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::_List_node<Vertex*> >]’
/usr/include/c++/10/bits/stl_list.h:637:33: required from ‘std::__cxx11::list<_Tp, _Alloc>::_Node* std::__cxx11::list<_Tp, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {Vertex&}; _Tp = Vertex*; _Alloc = std::allocator<Vertex*>; std::__cxx11::list<_Tp, _Alloc>::_Node = std::__cxx11::list<Vertex*>::_Node]’
/usr/include/c++/10/bits/stl_list.h:1911:32: required from ‘void std::__cxx11::list<_Tp, _Alloc>::_M_insert(std::__cxx11::list<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {Vertex&}; _Tp = Vertex*; _Alloc = std::allocator<Vertex*>; std::__cxx11::list<_Tp, _Alloc>::iterator = std::__cxx11::list<Vertex*>::iterator]’
/usr/include/c++/10/bits/stl_list.h:1227:19: required from ‘void std::__cxx11::list<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {Vertex&}; _Tp = Vertex*; _Alloc = std::allocator<Vertex*>]’
/usr/include/c++/10/bits/stl_list.h:1840:18: required from ‘void std::__cxx11::list<_Tp, _Alloc>::_M_initialize_dispatch(_InputIterator, _InputIterator, std::__false_type) [with _InputIterator = std::_List_iterator<Vertex>; _Tp = Vertex*; _Alloc = std::allocator<Vertex*>]’
/usr/include/c++/10/bits/stl_list.h:806:26: required from ‘std::__cxx11::list<_Tp, _Alloc>::list(_InputIterator, _InputIterator, const allocator_type&) [with _InputIterator = std::_List_iterator<Vertex>; <template-parameter-2-2> = void; _Tp = Vertex*; _Alloc = std::allocator<Vertex*>; std::__cxx11::list<_Tp, _Alloc>::allocator_type = std::allocator<Vertex*>]’
/home/etzl/projects/c-cpp/test/main.cc:58:87: required from here
/usr/include/c++/10/ext/new_allocator.h:150:4: error: cannot convert ‘Vertex’ to ‘Vertex*’ in initialization
150 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Build finished with error(s)
You should use std::unordered_set<Vertex*> currentLabelVertices instead of a list. It gives O(1) lookup instead of the O(n) solution you have with std::none_of().
Your other problem is here:
std::list<Vertex*> unlabeledVertices {graph.vertices.begin(), graph.vertices.end()};
It doesn't compile because graph.vertices contains Vertex instances, not pointers. The fix is simple:
std::list<Vertex*> unlabeledVertices;
for (auto& vertex : graph.vertices)
unlabeledVertices.push_back(&vertex);

Templatize downcasting to the derived class and call the corresponding method

I have a routine in the main.cpp where user will specify which mode to execute in the program. Once the mode is specified, the corresponding block will be executed - first downcast the parent solver to the child solver and call the associated solve method in the child class.
std::unique_ptr<SudokuSolver> solver;
if (mode == MODES::SEQUENTIAL_BACKTRACKING)
{
solver = std::make_unique<SudokuSolver_SequentialBacktracking>();
SudokuSolver_SequentialBacktracking* child_solver = dynamic_cast<SudokuSolver_SequentialBacktracking*>(solver.get());
child_solver->solve(board);
}
else if (mode == MODES::SEQUENTIAL_BRUTEFORCE)
{
solver = std::make_unique<SudokuSolver_SequentialBruteForce>();
SudokuSolver_SequentialBruteForce* child_solver = dynamic_cast<SudokuSolver_SequentialBruteForce*>(solver.get());
child_solver->solve(board);
}
else if (mode == MODES::PARALLEL_BRUTEFORCE)
{
int NUM_THREADS = (argc >= 5) ? std::stoi(argv[4]) : 2;
omp_set_num_threads(NUM_THREADS);
#pragma omp parallel
{
#pragma omp single nowait
{
solver = std::make_unique<SudokuSolver_ParallelBruteForce>();
SudokuSolver_ParallelBruteForce* child_solver = dynamic_cast<SudokuSolver_ParallelBruteForce*>(solver.get());
child_solver->solve(board);
}
}
}
else if (mode == MODES::SEQUENTIAL_DANCINGLINKS)
{
solver = std::make_unique<SudokuSolver_SequentialDLX>(board);
SudokuSolver_SequentialDLX* child_solver = dynamic_cast<SudokuSolver_SequentialDLX*>(solver.get());
child_solver->solve();
}
else if (mode == MODES::PARALLEL_DANCINGLINKS)
{
int NUM_THREADS = (argc >= 5) ? std::stoi(argv[4]) : 2;
omp_set_num_threads(NUM_THREADS);
#pragma omp parallel
{
#pragma omp single
{
solver = std::make_unique<SudokuSolver_ParallelDLX>(board);
SudokuSolver_ParallelDLX* child_solver = dynamic_cast<SudokuSolver_ParallelDLX*>(solver.get());
child_solver->solve();
}
}
}
I found it's kinda duplicates of code so I want to templatize them to something like:
template <typename T>
void downCastandSolve(std::unique_ptr<SudokuSolver> solver, SudokuBoard& board)
{
solver = std::make_unique<T>(board);
T* child_solver = dynamic_cast<T*>(solver.get());
child_solver->solve();
}
However, I got the following error message:
error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = SudokuSolver; _Dp = std::default_delete<SudokuSolver>]’
Not sure how to properly templatize the portions of code. Hope someone could help!
You would have much clearer code if solve function was virtual.
Also, either the constructor or the solve method should receive the board reference but not both. Having a single way make the code simpler to understand as each algorithm works the same way.
std::unique_ptr<SudokuSolver> CreateSolver(MODES mode)
{
switch (mode)
{
case MODES::SEQUENTIAL_BACKTRACKING:
return std::make_unique<SudokuSolver_SequentialBacktracking>();
...
}
}
Then assuming solve is virtual, the code resume to:
auto solver = CreateSolver(mode);
solver->solve(board);
solver->get_solution();
Any parallel stuff should be hidden inside the solve function when appropriate.
By writing code like that, it is much easier to read and you don't need an extra template function to share code as you avoid duplication from the start.
std::unique_ptrs are not copyable. You need to take it by reference:
void downCastandSolve(std::unique_ptr<SudokuSolver>& solver, SudokuBoard& board)
// ^

node js callback from native C++ code is throwing errors

I am trying to implement event listeners. Node js will subscribe to the events (using C++ function). When the event occurs, C++ should inform node js.
JS code:
pal.subscribeEvent("ONSTATECHANGE", function(a) { console.log("Event received for ONSTATECHAN";});
function kcb (a) {
console.log("KCB .....ONSTATECHAN"+JSON.stringify(a));
}
pal.subscribeEvent("ONSTATECHANGE", kcb);
C++ code:
struct deviceNapi {
Napi::Env env; // to store JS Function Env
Napi::Function jsCallback; // to Store JS function
};
//std::multimap<int, Napi::Function> deviceEventMgmt;
std::multimap<int, struct deviceNapi> deviceEventMgmt;
Napi::Value PAL::subscribeEvent(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
int eventID = info[0].As<Napi::Number>().Int32Value();
deviceNapi obj;
obj.env = env;
obj.jsCallback = info[1].As<Napi::Function>();
deviceEventMgmt.insert(std::make_pair(eventID, obj));
/*Napi::Function jsCallback = info[1].As<Napi::Function>();
deviceEventMgmt.insert(std::make_pair(eventID, jsCallback));*/
}
void ProcessDeviceEvent(int evt, DeviceEvtData data) {
switch(evt) {
case ONSTATECHANGE:
for(auto it = deviceEventMgmt.begin(); it != deviceEventMgmt.end(); it ++) {
if(it->first == ENUM_VERIZON_DEVICE_PENDING_RESET) {
Napi::Env env = it.second.env;
Napi::Object ret = Napi::Object::New(env);
ret.Set("reason", Napi::String::New(env, data.resetReason));
ret.Set("time", Napi::Number::New(env, data.seconds));
it->second.jsCallback.Call(ret);
}
}
/*for(auto it = deviceEventMgmt.begin(); it != deviceEventMgmt.end(); it ++) {
if(it->first == ENUM_VERIZON_DEVICE_PENDING_RESET) {
it->second.Call();
}
}*/
break;
default:
std::cout << "ProcessDeviceEvent : Currently not handling evt : " << evt << std::endl;
break;
}
}
C++ code is throwing below errors while compiling
../PAL.cpp: In member function 'Napi::Value PAL:: subscribeEvent(const Napi::CallbackInfo&)':
../PAL.cpp:1915:13: error: use of deleted function 'deviceNapi::deviceNapi()'
deviceNapi obj;
^~~
../PAL.cpp:1903:8: note: 'deviceNapi::deviceNapi()' is implicitly deleted because the default definition would be ill-formed:
struct deviceNapi {
^~~~~~~~~~
../PAL.cpp:1903:8: error: no matching function for call to 'Napi::Env::Env()'
Can any one please help me to how to fix this problem of storing Node function env into C++ map. I need to save the env so that I can send the response when calling Node callback.
Napi::Env doesn't have a default constructor so your deviceNapi struct's default constructor cannot initialise the env member so the compiler didn't generate it, but you try to call it on this line:
deviceNapi obj;
You can fix this by initialising it like this:
deviceNapi obj = {env, info[1].As<Napi::Function>()};

exitprompt.cpp:268:22: error: passing ‘const ExitPrompter’ as ‘this’ argument discards qualifiers [-fpermissive]

I'm trying to modify some C++ code but I and getting the following errors during build:
make[2]: Leaving directory '/home/runner/work/mythtv/mythtv/mythtv/programs/mythlcdserver'
cd mythshutdown/ && ( test -e Makefile || /usr/lib/x86_64-linux-gnu/qt5/bin/qmake -o Makefile /home/runner/work/mythtv/mythtv/mythtv/programs/mythshutdown/mythshutdown.pro QMAKE=/usr/lib/x86_64-linux-gnu/qt5/bin/qmake ) && make -f Makefile
exitprompt.cpp: In member function ‘void ExitPrompter::Confirm(MythPower::Feature) const’:
Makefile:4570: recipe for target 'obj/exitprompt.o' failed
exitprompt.cpp:268:22: error: passing ‘const ExitPrompter’ as ‘this’ argument discards qualifiers [-fpermissive]
make[2]: Leaving directory '/home/runner/work/mythtv/mythtv/mythtv/programs/mythfrontend'
DoHalt(true);
Makefile:89: recipe for target 'sub-mythfrontend-make_first' failed
^
exitprompt.cpp:39:6: note: in call to ‘void ExitPrompter::DoHalt(bool)’
void ExitPrompter::DoHalt(const bool Confirmed)
^~~~~~~~~~~~
exitprompt.cpp:270:24: error: passing ‘const ExitPrompter’ as ‘this’ argument discards qualifiers [-fpermissive]
DoReboot(true);
^
exitprompt.cpp:70:6: note: in call to ‘void ExitPrompter::DoReboot(bool)’
void ExitPrompter::DoReboot(const bool Confirmed)
^~~~~~~~~~~~
exitprompt.cpp:272:25: error: passing ‘const ExitPrompter’ as ‘this’ argument discards qualifiers [-fpermissive]
DoSuspend(true);
^
exitprompt.cpp:100:6: note: in call to ‘void ExitPrompter::DoSuspend(bool)’
void ExitPrompter::DoSuspend(const bool Confirmed)
^~~~~~~~~~~~
make[2]: *** [obj/exitprompt.o] Error 1
make[1]: *** [sub-mythfrontend-make_first] Error 2
The code is as follows:
// Qt
#include <QCoreApplication>
// MythTV
#include "config.h"
#include "exitprompt.h"
#include "mythcontext.h"
#include "mythdialogbox.h"
#include "mythmainwindow.h"
#include "mythscreenstack.h"
#include "mythsystemlegacy.h"
#include "mythlogging.h"
#include "exitcodes.h"
ExitPrompter::ExitPrompter()
: m_power(MythPower::AcquireRelease(this, true)),
m_haltCommand(gCoreContext->GetSetting("HaltCommand", "")),
m_rebootCommand(gCoreContext->GetSetting("RebootCommand", "")),
m_suspendCommand(gCoreContext->GetSetting("SuspendCommand", ""))
{
}
ExitPrompter::~ExitPrompter()
{
if (m_power)
MythPower::AcquireRelease(this, false);
}
void ExitPrompter::DoQuit()
{
qApp->exit();
}
void ExitPrompter::ConfirmHalt() const
{
Confirm(MythPower::FeatureShutdown);
}
void ExitPrompter::DoHalt(const bool Confirmed)
{
if (!Confirmed)
return;
// Use user specified command if it exists
if (!m_haltCommand.isEmpty())
{
uint ret = myth_system(m_haltCommand);
if (ret == GENERIC_EXIT_OK)
return;
LOG(VB_GENERAL, LOG_ERR,
"User defined HaltCommand failed, falling back to "
"alternative methods.");
}
// Otherwise use MythPower
if (m_power && m_power->IsFeatureSupported(MythPower::FeatureShutdown))
if (m_power->RequestFeature(MythPower::FeatureShutdown))
return;
// halt of last resort
myth_system("sudo /sbin/halt -p");
}
void ExitPrompter::ConfirmReboot() const
{
Confirm(MythPower::FeatureRestart);
}
void ExitPrompter::DoReboot(const bool Confirmed)
{
if (!Confirmed)
return;
if (!m_rebootCommand.isEmpty())
{
uint ret = myth_system(m_rebootCommand);
if (ret == GENERIC_EXIT_OK)
return;
LOG(VB_GENERAL, LOG_ERR,
"User defined RebootCommand failed, falling back to "
"alternative methods.");
}
// Otherwise use MythPower
if (m_power && m_power->IsFeatureSupported(MythPower::FeatureRestart))
if (m_power->RequestFeature(MythPower::FeatureRestart))
return;
// reboot of last resort
myth_system("sudo /sbin/reboot");
}
void ExitPrompter::ConfirmSuspend(void) const
{
Confirm(MythPower::FeatureSuspend);
}
void ExitPrompter::DoSuspend(const bool Confirmed)
{
if (!Confirmed)
return;
// Use user specified command if it exists
if (!m_suspendCommand.isEmpty())
{
uint ret = myth_system(m_suspendCommand);
if (ret == GENERIC_EXIT_OK)
return;
LOG(VB_GENERAL, LOG_ERR,
"User defined SuspendCommand failed, falling back to "
"alternative methods.");
}
if (m_power && m_power->IsFeatureSupported(MythPower::FeatureSuspend))
m_power->RequestFeature(MythPower::FeatureSuspend);
}
void ExitPrompter::DoStandby()
{
GetMythMainWindow()->IdleTimeout();
}
void ExitPrompter::HandleExit()
{
// HACK IsFrontendOnly() triggers a popup if there is no BE connection.
// We really don't need that right now. This hack prevents it.
gContext->SetDisableEventPopup(true);
// first of all find out, if this is a frontend only host...
bool frontendOnly = gCoreContext->IsFrontendOnly();
// HACK Undo the hack, just in case we _don't_ quit:
gContext->SetDisableEventPopup(false);
// how do you want to quit today?
bool allowExit = false;
bool allowReboot = false;
bool allowShutdown = false;
bool allowStandby = false;
bool allowSuspend = false;
bool haveshutdown = !m_haltCommand.isEmpty();
bool havereboot = !m_rebootCommand.isEmpty();
bool havesuspend = !m_suspendCommand.isEmpty();
#ifdef Q_OS_ANDROID
haveshutdown = false;
havereboot = false;
havesuspend = false;
#endif
if (m_power)
{
havereboot |= m_power->IsFeatureSupported(MythPower::FeatureRestart);
haveshutdown |= m_power->IsFeatureSupported(MythPower::FeatureShutdown);
havesuspend |= m_power->IsFeatureSupported(MythPower::FeatureSuspend);
}
switch (gCoreContext->GetNumSetting("OverrideExitMenu", 0))
{
case 0:
allowExit = true;
if (frontendOnly)
allowShutdown = haveshutdown;
break;
case 1:
allowExit = true;
break;
case 2:
allowExit = true;
allowShutdown = haveshutdown;
break;
case 3:
allowExit = true;
allowReboot = havereboot;
allowShutdown = haveshutdown;
break;
case 4:
allowShutdown = haveshutdown;
break;
case 5:
allowReboot = havereboot;
break;
case 6:
allowReboot = havereboot;
allowShutdown = haveshutdown;
break;
case 7:
allowStandby = true;
break;
case 8:
allowSuspend = havesuspend;
break;
case 9:
allowExit = true;
allowSuspend = havesuspend;
break;
}
MythScreenStack *ss = GetMythMainWindow()->GetStack("popup stack");
auto *dlg = new MythDialogBox(tr("Do you really want to exit MythTV?"), ss,
"exit prompt");
if (!dlg->Create())
{
LOG(VB_GENERAL, LOG_ERR, "Can't create Exit Prompt dialog?");
delete dlg;
DoQuit();
return;
}
dlg->AddButton(QCoreApplication::translate("(Common)", "No"));
if (allowExit)
dlg->AddButton(tr("Yes, Exit now"), SLOT(DoQuit()));
if (allowReboot)
dlg->AddButton(tr("Yes, Exit and Reboot"), SLOT(ConfirmReboot()));
if (allowShutdown)
dlg->AddButton(tr("Yes, Exit and Shutdown"), SLOT(ConfirmHalt()));
if (allowStandby)
dlg->AddButton(tr("Yes, Enter Standby Mode"), SLOT(DoStandby()));
if (allowSuspend)
dlg->AddButton(tr("Yes, Suspend"), SLOT(ConfirmSuspend()));
// This is a hack so that the button clicks target the correct slot:
dlg->SetReturnEvent(this, QString());
ss->AddScreen(dlg);
}
void ExitPrompter::Confirm(MythPower::Feature Action) const
{
MythScreenStack *ss = GetMythMainWindow()->GetStack("popup stack");
QString msg;
gContext->SetDisableEventPopup(true);
if (!gCoreContext->IsFrontendOnly())
{
// this is the only case where a prompt should be shown
msg.prepend(tr("Mythbackend is running on this system. "));
auto *dlg = new MythConfirmationDialog(ss, msg);
if (!dlg->Create())
{
delete dlg;
DoQuit();
return;
}
if (Action == MythPower::FeatureShutdown)
connect(dlg, &MythConfirmationDialog::haveResult, this, &ExitPrompter::DoHalt);
else if (Action == MythPower::FeatureRestart)
connect(dlg, &MythConfirmationDialog::haveResult, this, &ExitPrompter::DoReboot);
else if (Action == MythPower::FeatureSuspend)
connect(dlg, &MythConfirmationDialog::haveResult, this, &ExitPrompter::DoSuspend);
ss->AddScreen(dlg);
}
else
{
// no prompts required, take a specific action required
// calling these exitprompter functions with (true) fails build
if (Action == MythPower::FeatureShutdown)
DoHalt(true);
else if (Action == MythPower::FeatureRestart)
DoReboot(true);
else if (Action == MythPower::FeatureSuspend)
DoSuspend(true);
}
gContext->SetDisableEventPopup(false);
}
I have already tried adding const to the end of the DoHalt (etc) functions like:
void ExitPrompter::DoHalt(const bool Confirmed) const
void ExitPrompter::DoReboot(const bool Confirmed) const
void ExitPrompter::DoSuspend(const bool Confirmed) const
But this just gives me a different error during build like:
cd mythshutdown/ && ( test -e Makefile || /usr/lib/x86_64-linux-gnu/qt5/bin/qmake -o Makefile /home/runner/work/mythtv/mythtv/mythtv/programs/mythshutdown/mythshutdown.pro QMAKE=/usr/lib/x86_64-linux-gnu/qt5/bin/qmake ) && make -f Makefile
exitprompt.cpp:39:6: error: prototype for ‘void ExitPrompter::DoHalt(bool) const’ does not match any in class ‘ExitPrompter’
void ExitPrompter::DoHalt(const bool Confirmed) const
^~~~~~~~~~~~
In file included from exitprompt.cpp:6:0:
exitprompt.h:14:10: error: candidate is: void ExitPrompter::DoHalt(bool)
Makefile:4570: recipe for target 'obj/exitprompt.o' failed
void DoHalt(bool Confirmed = true);
make[2]: Leaving directory '/home/runner/work/mythtv/mythtv/mythtv/programs/mythfrontend'
^~~~~~
Makefile:89: recipe for target 'sub-mythfrontend-make_first' failed
exitprompt.cpp:70:6: error: prototype for ‘void ExitPrompter::DoReboot(bool) const’ does not match any in class ‘ExitPrompter’
void ExitPrompter::DoReboot(const bool Confirmed) const
^~~~~~~~~~~~
In file included from exitprompt.cpp:6:0:
exitprompt.h:15:10: error: candidate is: void ExitPrompter::DoReboot(bool)
void DoReboot(bool Confirmed = true);
^~~~~~~~
exitprompt.cpp:100:6: error: prototype for ‘void ExitPrompter::DoSuspend(bool) const’ does not match any in class ‘ExitPrompter’
void ExitPrompter::DoSuspend(const bool Confirmed) const
^~~~~~~~~~~~
In file included from exitprompt.cpp:6:0:
exitprompt.h:17:10: error: candidate is: void ExitPrompter::DoSuspend(bool)
void DoSuspend(bool Confirmed = true);
^~~~~~~~~
exitprompt.cpp: In member function ‘void ExitPrompter::Confirm(MythPower::Feature) const’:
exitprompt.cpp:268:22: error: passing ‘const ExitPrompter’ as ‘this’ argument discards qualifiers [-fpermissive]
DoHalt(true);
^
In file included from exitprompt.cpp:6:0:
exitprompt.h:14:10: note: in call to ‘void ExitPrompter::DoHalt(bool)’
void DoHalt(bool Confirmed = true);
^~~~~~
exitprompt.cpp:270:24: error: passing ‘const ExitPrompter’ as ‘this’ argument discards qualifiers [-fpermissive]
DoReboot(true);
^
In file included from exitprompt.cpp:6:0:
exitprompt.h:15:10: note: in call to ‘void ExitPrompter::DoReboot(bool)’
void DoReboot(bool Confirmed = true);
^~~~~~~~
exitprompt.cpp:272:25: error: passing ‘const ExitPrompter’ as ‘this’ argument discards qualifiers [-fpermissive]
DoSuspend(true);
^
In file included from exitprompt.cpp:6:0:
exitprompt.h:17:10: note: in call to ‘void ExitPrompter::DoSuspend(bool)’
void DoSuspend(bool Confirmed = true);
^~~~~~~~~
make[2]: *** [obj/exitprompt.o] Error 1
make[1]: *** [sub-mythfrontend-make_first] Error 2
I don't know C++ (I though the change I was making was fairly simple!) very well at all so I need some precise help.
Thanks

Call to non-constexpr function 'std::map...'

I'm attempting to create a pseudo-media center thing on an Arduino and a breadboard, not all that complicated but this is my first project with C++ that amounted to more than 'Hello world!' or a calculator.
Digressing to my point though, I started rewriting almost the entire original program, and in an effort to clean things up, started using a map to hold the keys and values (IR codes), and to further organize it, put the assignments inside of a function (IR_generateMap()), but I'm getting an error when I compile it.
C:\Users\trevo\Documents\Arduino\improvedIRRemote\improvedIRRemote.ino: In function 'void IRLoop(bool)':
improvedIRRemote:78: error: call to non-constexpr function 'std::map<Key, T, Compare, Allocator>::reference std::map<Key, T, Compare, Allocator>::operator[](const key_type&) [with Key = std::basic_string<char>; T = int; Compare = std::less<std::basic_string<char> >; Allocator = std::allocator<int>; std::map<Key, T, Compare, Allocator>::reference = int&; std::map<Key, T, Compare, Allocator>::key_type = std::basic_string<char>]'
case IRCodes["Power Button"]:
^
improvedIRRemote:78: error: call to non-constexpr function 'std::map<Key, T, Compare, Allocator>::reference std::map<Key, T, Compare, Allocator>::operator[](const key_type&) [with Key = std::basic_string<char>; T = int; Compare = std::less<std::basic_string<char> >; Allocator = std::allocator<int>; std::map<Key, T, Compare, Allocator>::reference = int&; std::map<Key, T, Compare, Allocator>::key_type = std::basic_string<char>]'
exit status 1
call to non-constexpr function 'std::map<Key, T, Compare, Allocator>::reference std::map<Key, T, Compare, Allocator>::operator[](const key_type&) [with Key = std::basic_string<char>; T = int; Compare = std::less<std::basic_string<char> >; Allocator = std::allocator<int>; std::map<Key, T, Compare, Allocator>::reference = int&; std::map<Key, T, Compare, Allocator>::key_type = std::basic_string<char>]'
I've looked up and attempted to understand errors with non-constexpr calls, but to be perfectly honest, I don't understand how what I'm trying to do with the map relates to the problems being described in the posts that deal with said error.
#include <IRremote.h>
#include <StandardCplusplus.h>
#include <map>
//Variables responsible for recieving and decoding IR signals/codes.
IRrecv receiver(10); //IR receiver initialization.
decode_results results; //Object that is responsible for decoding the IR signal.
//Variables responsible for tracking channel changing.
int channel = 1; //The active channel.
int desiredChannel = ""; //The string that is used to concatenate the numbers pressed on the remote keypad together.
int channelEnterDelay = 4000; //The delay between the last time a number was pressed on the remote keypad and when the desiredChannel is cleared.
unsigned long channelEnterStartTime = 0; //The time in which that last number was pressed on the remote keypad.
String intConverter; //The string responsible for casting an integer to a string.
//Variables responsible for tracking volume changing.
int volume = 50; //The current volume.
int lastVolume = 50; //Holds the value of the volume previous to the volume being muted.
bool isMuted = false; //Whether or not the sound has been muted.
//Map responsible for the setting and getting of IR codes and their respective keys.
const std::map<std::string, int> IRCodes;
//Miscellanious Stuff - mostly waiting for depreciation.
int IRFlasherPin = 8;
int mode = 0;
int IRFlasherBlinkRate = 10;
//Debug mode shows channel switching info when entering from the remote keypad, turn it off to declutter the serial feed if it is not being used.
bool DEBUG_MODE = false;
void setup() {
receiver.enableIRIn(); //Tells the receiver to start listening for IR communication.
pinMode(IRFlasherPin, OUTPUT); //Configuring the pin that flashes upon recieving the 'excess communication' IR code.
Serial.begin(9600); //Begins serial communication at 9600 baud.
IR_generateMap(); //Sets all of the values for the map of IR keys and values.
//Ready message.
Serial.println("The Arduino is ON and ready for communication.");
if (DEBUG_MODE) { Serial.println("Also please note that debug mode has been preemptively enabled. The serial monitor can be expected to be much more cluttered than normal. To disable this, press the 'U/SD' button on the remote."); }
Serial.println();
}
void loop() {
//Pre-loop checks.
//empty
IRLoop(true);
}
void IRLoop(bool toldToContinueLooking) {
if (receiver.decode(&results)) {
switch(results.value) {
case IRCodes["Power Button"]:
Serial.println("Power Toggle");
break;
default:
if (DEBUG_MODE) {
Serial.print("Extraneous code: ");
Serial.print(results.value);
}
break;
}
}
if (toldToContinueLooking) { receiver.resume(); }
}
void IR_generateMap() {
//General Keys
IRCodes["Power Button"] = 16753245;
IRCodes["Mode Button"] = 16736925;
IRCodes["Back Button"] = 16750695;
IRCodes["EQ Button"] = 16769055;
IRCodes["USD Button"] = 16756815;
//Media Keys
IRCodes["PlayPause Button"] = 16720605;
IRCodes["Rewind Button"] = 16712445;
IRCodes["Fast Forward Button"] = 16761405;
//Volume Keys
IRCodes["Mute Button"] = 16769565;
IRCodes["Minus Button"] = 16754775;
IRCodes["Plus Button"] = 16748655;
//Numpad Keys
IRCodes["Numpad 0"] = 16738455;
IRCodes["Numpad 1"] = 16724175;
IRCodes["Numpad 2"] = 16718055;
IRCodes["Numpad 3"] = 16743045;
IRCodes["Numpad 4"] = 16716015;
IRCodes["Numpad 5"] = 16726215;
IRCodes["Numpad 6"] = 16734885;
IRCodes["Numpad 7"] = 16728765;
IRCodes["Numpad 8"] = 16730805;
IRCodes["Numpad 9"] = 16732845;
//Non-Key Codes
IRCodes["Excess Communication"] = 4294967295;
}
Can someone explain what I'm doing wrong to me in terms that someone of my early C++ knowledge-base would understand?
The expression in the 'case' must be compile time constant. Just use an if/else construction instead and it should work.
Thomas
I'd go in opposite way by using map to decode IR Code to handler function or by using enum. Something like this:
#include <StandardCplusplus.h>
#include <map>
#include <functional>
void power_key();
void num_key0();
void num_key1();
void num_key2();
void num_key3();
void num_key4();
void num_key5();
void num_key6();
void num_key7();
void num_key8();
void num_key9();
void num_key(int8_t);
typedef void(*handler_t)();
std::map<uint32_t, handler_t> keys;
void setup() {
keys[16753245UL] = power_key;
keys[16738455UL] = num_key0;
keys[16724175UL] = num_key1;
keys[16718055UL] = num_key2;
keys[16743045UL] = num_key3;
keys[16716015UL] = num_key4;
keys[16726215UL] = num_key5;
keys[16734885UL] = num_key6;
keys[16728765UL] = num_key7;
keys[16730805UL] = num_key8;
keys[16732845UL] = num_key9;
Serial.begin(57600);
}
void loop() {
uint32_t recvd_code = 16753245UL; // literal value, for testing purpose without IR receiver and remote
auto iter = keys.find(recvd_code); // find received code and execute it
if (iter != keys.end()) {
iter->second();
} else {
Serial.print(F("IR Code "));
Serial.print(recvd_code);
Serial.println(F("not found"));
}
delay(1000);
}
void power_key() {
Serial.println(F("Power key pressed"));
}
void num_key0() { num_key(0); }
void num_key1() { num_key(1); }
void num_key2() { num_key(2); }
void num_key3() { num_key(3); }
void num_key4() { num_key(4); }
void num_key5() { num_key(5); }
void num_key6() { num_key(6); }
void num_key7() { num_key(7); }
void num_key8() { num_key(8); }
void num_key9() { num_key(9); }
void num_key(int8_t num) {
Serial.print(F("Numeric key pressed: "));
Serial.println(num);
}
Initializer list somehow didin't work, so initialization must be done in setup and map can't be const.