Compile problem
Unsolved
C++ Gurus
-
wrote on 1 Sept 2019, 16:43 last edited by
Hello guys,
Im getting this error when attempting to compile:
U:\proj\dfw\mainwindow.cpp:-1: error: undefined reference to `void ui_sync_and_save::addUiItem<int>(QObject*, int&, uiItemMath, double)'
mainWin .h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "../usual/ui_sync_and_save.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); ui_sync_and_save test; int val=0; private slots: private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H } MainWindow::~MainWindow() { delete ui; }
mainWin .cpp
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); test.addUiItem(ui->checkBox,val);//compile problem occurs here<<<<< } MainWindow::~MainWindow() { delete ui; }
include .h
#ifndef UI_SYNC_AND_SAVE_H #define UI_SYNC_AND_SAVE_H #include <QObject> #include "QSettings" using namespace std; enum uiOp{ valToUi, valFromUi, fileFromUi, fileToUiAndPtr }; enum uiItemMath{ noCorrection,add,rem,multip,divide }; class ui_sync_and_save : public QObject { // Q_OBJECT public: ui_sync_and_save(); enum uiItems{ spinBox,doubleSpinBox,checkBox,radioButton,dateTimeEdit }; struct uiItem{ QObject*ptr; void*valPtr; bool writeLock=0; uiItems type; uiItemMath mathOp; double mathVal; }; vector<uiItem>uiItems; template <typename S> void addUiItem(QObject*uiItem,S&setVariable,uiItemMath correctionOp=noCorrection,double correctionVal=0); void syncUiVals(QObject *target=NULL, uiOp op=uiOp::valFromUi); QSettings uiSet; void saveUiValsToFile(QString path); void loadUiValsFromFile(QString path); bool setWriteLock(QObject*uiItem, bool lock); template <typename Val> QString n(Val num,char decimals=2){ if(typeid(num)==typeid(double)){ return QString::number(num,'f',decimals); }else{ return QString::number(num); } } private: template <typename V> V valCorrection(V val,uiItem&itm,uiOp op=valFromUi); public slots: void syncSingleVal(); signals: QString errorMsg(QString error){ return error; } }; #endif // UI_SYNC_AND_SAVE_H
include .cpp
#include "ui_sync_and_save.h" #include "QDoubleSpinBox" #include "QSpinBox" #include "QCheckBox" #include "QRadioButton" #include "QDateTimeEdit" ui_sync_and_save::ui_sync_and_save() { } template<typename S>//possibly template related mistake here<<<<<<<< void ui_sync_and_save::addUiItem(QObject *uiItem, S &setVar, uiItemMath mathOp, double mathVal) { ui_sync_and_save::uiItem item; item.ptr=uiItem; item.valPtr=&setVar; item.mathOp=mathOp; item.mathVal=mathVal; QDoubleSpinBox*dsBox=qobject_cast<QDoubleSpinBox*>(item.ptr); if (dsBox != NULL){ item.type=doubleSpinBox; connect(dsBox, SIGNAL(valueChanged(double)), this, SLOT(syncSingleVal())); uiItems.emplace_back(item); return; } QSpinBox*sBox=qobject_cast<QSpinBox*>(item.ptr); if (sBox != NULL){ item.type=spinBox; connect(sBox, SIGNAL(valueChanged(int)), this, SLOT(syncSingleVal())); uiItems.emplace_back(item); return; } QCheckBox*cBox=qobject_cast<QCheckBox*>(item.ptr); if (cBox != NULL){ item.type=checkBox; connect(cBox, SIGNAL(stateChanged(int)), this, SLOT(syncSingleVal())); uiItems.emplace_back(item); return; } QRadioButton*rBut=qobject_cast<QRadioButton*>(item.ptr); if (rBut != NULL){ item.type=radioButton; connect(rBut, SIGNAL(pressed()), this, SLOT(syncSingleVal())); uiItems.emplace_back(item); return; } QDateTimeEdit*dtEdit=qobject_cast<QDateTimeEdit*>(item.ptr); if (dtEdit != NULL){ item.type=dateTimeEdit; connect(dtEdit, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(uuendaSet())); uiItems.emplace_back(item); return; } emit errorMsg("UiItemCastsFailed"); } #ifdef QT_DEBUG int nullCounter=0; #endif void ui_sync_and_save::syncUiVals(QObject *target,uiOp op) { #ifdef QT_DEBUG if(op==uiOp::valFromUi && target==NULL){ nullCounter++; if(nullCounter>1) emit errorMsg("loopTroughUiItems NULL passed "+n(nullCounter)+" times.. Could use only once for initialization and set loading"); } #endif bool found=0; for(auto &item:uiItems){ if((target!=NULL && item.ptr!=target)||(item.writeLock&&op==uiOp::valFromUi)){ continue; }else{ found=1; } switch (item.type) { case spinBox:{ QSpinBox*sBox=qobject_cast<QSpinBox*>(item.ptr); if (sBox != NULL){ int*p=(int*)item.valPtr; switch (op){ case uiOp::valToUi: sBox->setValue(valCorrection(*p,item,uiOp::valToUi)); continue; case uiOp::valFromUi: *p=valCorrection(sBox->value(),item); ; continue; case uiOp::fileFromUi: uiSet.setValue(sBox->objectName(), sBox->value()); continue; case uiOp::fileToUiAndPtr: sBox->setValue(uiSet.value(sBox->objectName()).toInt()); continue; } }} case doubleSpinBox:{ QDoubleSpinBox*dsBox=qobject_cast<QDoubleSpinBox*>(item.ptr); if (dsBox != NULL){ double*p=(double*)item.valPtr; switch (op){ case uiOp::valToUi: dsBox->setValue(valCorrection(*p,item,uiOp::valToUi)); continue; case uiOp::valFromUi: *p=valCorrection(dsBox->value(),item); continue; case uiOp::fileFromUi: uiSet.setValue(dsBox->objectName(), dsBox->value()); continue; case uiOp::fileToUiAndPtr: dsBox->setValue(uiSet.value(dsBox->objectName()).toDouble()); continue; } }} case checkBox:{ QCheckBox*cBox=qobject_cast<QCheckBox*>(item.ptr); if (cBox != NULL){ bool*p=(bool*)item.valPtr; switch (op){ case uiOp::valToUi: cBox->setChecked(*p); continue; case uiOp::valFromUi: *p=cBox->isChecked(); continue; case uiOp::fileFromUi: uiSet.setValue(cBox->objectName(), cBox->isChecked()); continue; case uiOp::fileToUiAndPtr: cBox->setChecked(uiSet.value(cBox->objectName()).toBool()); continue; } }} case radioButton:{ QRadioButton*rBut=qobject_cast<QRadioButton*>(item.ptr); if (rBut != NULL){ bool*p=(bool*)item.valPtr; switch (op){ case uiOp::valToUi: rBut->setChecked(*p); continue; case uiOp::valFromUi: *p=rBut->isChecked(); continue; case uiOp::fileFromUi: uiSet.setValue(rBut->objectName(), rBut->isChecked()); continue; case uiOp::fileToUiAndPtr: rBut->setChecked(uiSet.value(rBut->objectName()).toBool()); continue; } } } case dateTimeEdit:{ QDateTimeEdit*dtEdit=qobject_cast<QDateTimeEdit*>(item.ptr); if (dtEdit != NULL){ QDateTime*p=(QDateTime*)item.valPtr; switch (op){ case uiOp::valToUi: dtEdit->setDateTime(*p); continue; case uiOp::valFromUi: *p=dtEdit->dateTime(); continue; case uiOp::fileFromUi: uiSet.setValue(dtEdit->objectName(), dtEdit->dateTime()); continue; case uiOp::fileToUiAndPtr: dtEdit->setDateTime(uiSet.value(dtEdit->objectName()).toDateTime()); continue; } }} default:{ emit errorMsg("ui CaseNotDefined or type and passed ptr mismatch, nam: "+item.ptr->objectName()); continue; } } if(!found) emit errorMsg("ui ptr not found , nam:"+item.ptr->objectName()); } if(op==uiOp::fileToUiAndPtr){ syncUiVals(NULL,uiOp::valFromUi); #ifdef QT_DEBUG nullCounter--; #endif } } void ui_sync_and_save::syncSingleVal(){ syncUiVals(sender());//should return ptr of signal caller widget } void ui_sync_and_save::saveUiValsToFile(QString path) { uiSet.setPath(QSettings::IniFormat,QSettings::UserScope, path); syncUiVals(NULL,uiOp::fileFromUi); } void ui_sync_and_save::loadUiValsFromFile(QString path) { uiSet.setPath(QSettings::IniFormat,QSettings::UserScope, path); syncUiVals(NULL,uiOp::fileToUiAndPtr); } bool ui_sync_and_save::setWriteLock(QObject *uiItem,bool lock) { for(auto &item:uiItems){ if(item.ptr==uiItem){ item.writeLock=lock; return 1; } } return 0; } template<typename V> V ui_sync_and_save::valCorrection(V val, uiItem &itm,uiOp op) { switch (itm.mathOp) { noCorrection: return val; add: if(op=valFromUi){ return val-itm.mathVal; }else{ return val+itm.mathVal; } rem: if(op=valFromUi){ return val+itm.mathVal; }else{ return val-itm.mathVal; } multip: if(op=valFromUi){ return val/itm.mathVal; }else{ return val*itm.mathVal; } div: if(op=valFromUi){ return val*itm.mathVal; }else{ return val/itm.mathVal; } } }
All help is welcome.
-
Templates are instantiated at the call site, so their body needs to be available at that point. The error says it's not.
To fix this and as a general rule of thumb - move your template implementation to the header file. -
wrote on 1 Sept 2019, 20:06 last edited by
Wonderful , also had some problems with using signals improperly.
1/3