-3

in my project if I define base class Base_Dialog as non template and then try to assign 'caller' in already_exists_ it works in the way expected but if I make Base_Dialog as a template class then the algorithm 'already_exists_' (unchanged) will not work and caller will not change (this is especially intriguing that the algorithm is unchanged and yet once works and other time it doesn't):

//This is minimal example (I know it's somewhat longer than usual but in order to show what I mean it needs to be this length)

MAIN_DIALOG_HPP

    #ifndef MAIN_DIALOG_HPP
    #define MAIN_DIALOG_HPP
    #include <QSet>
    #include <QtDebug>
    #include "Base_Dialog.hpp"
    #include "ui_Main_Dialog.h"
    #include "_1Dialog.hpp"
    #include "_2Dialog.hpp"
/*The following approach will not work*/
    class Main_Dialog : public Base_Dialog<Ui::Main_Dialog>
    {
/*but if I would do as below (changing Base_Dialog to non-template) it will work:*/
//class Main_Dialog : public QDialog, private Ui::Main_Dialog, public Base_Dialog
        Q_OBJECT
        QSet<QDialog*>* dialogs_;
    private:
        template<class Dialog,class Caller>
        bool already_created_(Caller*const&, QDialog*& already_exists);

        template<class Dialog,class Caller, class Parent>
        QDialog* create_(Caller*const&,Parent*const&);

    public:
        explicit Main_Dialog(QWidget *parent = 0);
        template<class Dialog,class Caller>
        QDialog* get_dialog(Caller*const& caller);
    public slots:
        void _1clicked()
        {
            this->hide();
            get_dialog<_1Dialog>(this)->show();
        }
        void _2clicked()
        {
            this->hide();
            get_dialog<_2Dialog>(this)->show();
        }
    };

    template<class Dialog,class Caller>
    bool Main_Dialog::already_created_(Caller*const& caller,QDialog*& already_exists)
    {/*the already_exists is introduced here in order to remove repetions of code and
       searching*/
        auto beg = dialogs_->begin();
        auto end = dialogs_->end();
        while(beg != end)
        {
            if(dynamic_cast<Dialog*>(*beg))
            {
                already_exists = *beg;
                static_cast<Base_Dialog*>(already_exists)->set_caller(caller);
                return true;
            }

            ++beg;
        }
        return false;
    }

    template<class Dialog,class Caller, class Parent>
    QDialog* Main_Dialog::create_(Caller *const&caller, Parent *const&parent)
    {
        return (*dialogs_->insert(new Dialog(this,caller,parent)));
    }

    template<class Dialog,class Caller>
    QDialog* Main_Dialog::get_dialog(Caller *const&caller)
    {
        QDialog* already_exists = nullptr;
        if (already_created_<Dialog>(caller,already_exists))
        {
            return already_exists;
        }
        else
        {
            return create_<Dialog>(caller,this);
        }
    }

    Main_Dialog::Main_Dialog(QWidget *parent) :
        Base_Dialog<Ui::Main_Dialog>(this,this,parent),dialogs_(new QSet<QDialog*>)
    {
        setupUi(this);
    }

    #endif // MAIN_DIALOG_HPP

BASE_DIALOG_HPP

#ifndef BASE_DIALOG_HPP
#define BASE_DIALOG_HPP
#include <QDialog>
#include <QString>

class Main_Dialog;
template<class Ui_Dialog>
class Base_Dialog : public QDialog, protected Ui_Dialog
{
   // Q_OBJECT //no signals/slots
protected:
    Main_Dialog* main_dlg_;
    QDialog* caller_;

public:
    Base_Dialog(Main_Dialog *const &main_dlg, QDialog *const&caller, QWidget *parent = nullptr);
    QDialog* set_caller(QDialog *const&);
    QDialog* clear_caller();
    Main_Dialog* clear_main_dlg();

};

/*----------------*/
//#include "Main_Dialog.hpp"
template<class Ui_Dialog>
Base_Dialog<Ui_Dialog>::Base_Dialog(Main_Dialog *const&main_dlg,QDialog *const&caller, QWidget *parent):
    QDialog(parent),
    main_dlg_(main_dlg),
    caller_(caller)
{
    //setupUi(this);
}


#include <QtDebug>
template<class Ui_Dialog>
QDialog* Base_Dialog<Ui_Dialog>::set_caller(QDialog *const&new_caller)
{
 QDialog* old_caller = caller_;

 caller_ = new_caller;

 return old_caller;
}
#endif

_1DIALOG_HPP

#ifndef _1DIALOG_HPP
#define _1DIALOG_HPP
#include "Base_Dialog.hpp"
#include "ui__1Dialog.h"

class Main_Dialog;
class _1Dialog : public Base_Dialog<Ui::_1Dialog>
{
    Q_OBJECT
public:
    explicit _1Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent = 0);

private slots:
    void _2clicked();
    void caller_clicked();
    void main_clicked();
};

#endif // _1DIALOG_HPP

_1Dialog cpp

//_1Dialog cpp
#include "_1Dialog.hpp"
#include "_2Dialog.hpp"
#include "Main_Dialog.hpp"
_1Dialog::_1Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent) :
    Base_Dialog<Ui::_1Dialog>(main_dlg,caller,parent)
{
    setupUi(this);
}

void _1Dialog::_2clicked()
{
    this->hide();
    main_dlg_->get_dialog<_2Dialog>(this)->show();
}


void _1Dialog::caller_clicked()
{
    this->hide();
    caller_->show();
}

void _1Dialog::main_clicked()
{
    this->hide();
    main_dlg_->show();
}

_2DIALOG_HPP

#ifndef _2DIALOG_HPP
#define _2DIALOG_HPP
#include "Base_Dialog.hpp"
#include "ui__2Dialog.h"
class Main_Dialog;
class _2Dialog : public Base_Dialog<Ui::_2Dialog>//,private Ui::_2Dialog
{
    Q_OBJECT
private:


public:
    explicit _2Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent = 0);
private slots:
    void _1clicked();
    void caller_clicked();
    void main_clicked();
};

#endif // _2DIALOG_HPP

_2Dialog cpp

//_2Dialog cpp
#include "_2Dialog.hpp"
#include "_1Dialog.hpp"
#include "Main_Dialog.hpp"

_2Dialog::_2Dialog(Main_Dialog* main_dlg, QDialog*caller, QWidget *parent) :
    Base_Dialog<Ui::_2Dialog>(main_dlg,caller,parent)
{
    setupUi(this);
}


void _2Dialog::_1clicked()
{
    this->hide();
    main_dlg_->get_dialog<_1Dialog>(this)->show();
}

void _2Dialog::caller_clicked()
{
    this->hide();
    caller_->show();
}

void _2Dialog::main_clicked()
{
    this->hide();
    main_dlg_->show();
}

Why is this behavior? Algorithm is unchanged and yet once it assigns correctly and the other time it doesn't?

sehe
  • 374,641
  • 47
  • 450
  • 633
user336635
  • 2,081
  • 6
  • 24
  • 30
  • 3
    Read [this](http://stackoverflow.com/a/228797/14065). Then stop using identifiers that begin with `_` – Martin York Dec 20 '11 at 07:32
  • @LokiAstari read this: 'identifiers beginning with an underscore and an uppercase letter' and try to understand what you've just read before you jump into incorrect conclusion. – user336635 Dec 20 '11 at 07:35
  • Reserved in the global namespaces: identifiers beginning with an underscore All your classes are in the global namespace. Hence _1Dialog and _2Dialog violate the rules and I was not even looking that hard. – Martin York Dec 20 '11 at 07:37
  • The problem is that the rules are non obvious. As you can see even **you got it wrong**. By not using `_` as the first letter in an indetifier you avoid all the problems of having to remember the complex rules. – Martin York Dec 20 '11 at 07:39
  • @LokiAstari I did not get it wrong, **you just don't understand** what you read – user336635 Dec 20 '11 at 07:47
  • @LokiAstari so if the rules are as you're saying not obvious how can you be sure that you're right? You're wrong by the way. – user336635 Dec 20 '11 at 07:53
  • 1
    You are having a problem with dynamic cast in a templated hierarchy. Please update your question accordingly. And yes, the minimum example would be <10% of this code. – sehe Dec 20 '11 at 07:54
  • @user336635: That's a bold statement for somebody with broken code. But go on; why don't I understand. I am quite willing to delete my comments. PS. The macros you use are also broken _2DIALOG_HPP/_1DIALOG_HPP – Martin York Dec 20 '11 at 07:58
  • @sehe thanks for your comment, how shall I update my question? I really cannot see how it can be minimized by 90%. It will just not work. – user336635 Dec 20 '11 at 07:58
  • @LokiAstari names starting with underscore and CAPITAL letter are forbidden, my starts with an underscore and a digit, that's why I believe there is nothing wrong with this name. – user336635 Dec 20 '11 at 08:00
  • @user336635: From C++03 **17.4.3.2.1 Global names [lib.global.names]** Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.165 Your quoting: **7.1.3 Reserved identifiers** All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use. from the C standard. Did you actually read the link I provided it actually has all the appropriate sections of the standard referenced. – Martin York Dec 20 '11 at 08:04
  • @LokiAstari yes but my isn't in global namespace – user336635 Dec 20 '11 at 08:06
  • @user336635: In the code above they are. Also you macros are defintely in the global namespace (as they are in all namespaces) – Martin York Dec 20 '11 at 08:08
  • @LokiAstari but this is all for nothing - this is just a demo, this isn't a real problem here, the real problem seems to be unresolved. – user336635 Dec 20 '11 at 08:10
  • @user336635: How do you know it is not the problem. You could be conflicting with some system identifier that is causing all sorts of problems. Since you don't know the problem in your code then you should fix all discrepancy until you find the problem. – Martin York Dec 20 '11 at 08:18
  • @LokiAstari I,ve changed those identifiers to dialog_one etc and the problem remains. – user336635 Dec 20 '11 at 08:26
  • Sorry to hear that. It will be hard for people to help you though as problems like this require some investigation and digging and you have not provided a simple enough example that makes that digging easy (if fact near imposable to even compile this code without lots of domain knowledge). You really do need to try and simplify this (the act of simplifying the code usually shows the answer). Sorry I can not be of more use (I will keep watch in case you manage to provide something easy to compile). – Martin York Dec 20 '11 at 08:38
  • @LokiAstari this I believe cannot be simplified, but if you willing I can send you compilable and workable project, so you don't have to do anything just run and play and see what I'm talking about. Let me know if you up for it. – user336635 Dec 20 '11 at 08:55
  • #sehe +1 for pointing me into right direction. Thanks. – user336635 Dec 20 '11 at 12:46

1 Answers1

0

In already_exists_ change line:

static_cast<Base_Dialog*>(already_exists)->set_caller(caller);  

to:

static_cast<Dialog*>(already_exists)->set_caller(caller);

and add virtual inheritance for QDialog in Base_Dialog

@sehe, I want to thank you for pointing me into right direction, which allow me to resolve this problem. Great thanks, +1;

user336635
  • 2,081
  • 6
  • 24
  • 30