Error invalid use of incomplete type

I'm trying to use a typedef from a subclass in my project, I've isolated my problem in the example below. Does anyone know where I'm going wrong? template class A { p...

I’m trying to use a typedef from a subclass in my project, I’ve isolated my problem in the example below.

Does anyone know where I’m going wrong?

template<typename Subclass>
class A {
    public:
        //Why doesn't it like this?
        void action(typename Subclass::mytype var) {
            (static_cast<Subclass*>(this))->do_action(var);
        }
};

class B : public A<B> {
    public:
        typedef int mytype;

        B() {}

        void do_action(mytype var) {
            // Do stuff
        }
};

int main(int argc, char** argv) {
    B myInstance;
    return 0;
}

This is the output I get:

sean@SEAN-PC:~/Documents/LucadeStudios/experiments$ g++ -o test test.cpp
test.cpp: In instantiation of ‘A<B>’:
test.cpp:10:   instantiated from here
test.cpp:5: error: invalid use of incomplete type ‘class B’
test.cpp:10: error: forward declaration of ‘class B’

asked Mar 16, 2009 at 21:07

seanhodges's user avatar

seanhodgesseanhodges

17.3k15 gold badges70 silver badges93 bronze badges

The reason is that when instantiating a class template, all its declarations (not the definitions) of its member functions are instantiated too. The class template is instantiated precisely when the full definition of a specialization is required. That is the case when it is used as a base class for example, as in your case.

So what happens is that A<B> is instantiated at

class B : public A<B>

at which point B is not a complete type yet (it is after the closing brace of the class definition). However, A<B>::action‘s declaration requires B to be complete, because it is crawling in the scope of it:

Subclass::mytype

What you need to do is delaying the instantiation to some point at which B is complete. One way of doing this is to modify the declaration of action to make it a member template.

template<typename T>
void action(T var) {
    (static_cast<Subclass*>(this))->do_action(var);
}

It is still type-safe because if var is not of the right type, passing var to do_action will fail.

answered Mar 16, 2009 at 21:36

Johannes Schaub - litb's user avatar

1

You can get around this by using a traits class:
It requires you set up a specialsed traits class for each actuall class you use.

template<typename SubClass>
class SubClass_traits
{};

template<typename Subclass>
class A {
    public:
        void action(typename SubClass_traits<Subclass>::mytype var)
        {
                (static_cast<Subclass*>(this))->do_action(var);
        }
};


// Definitions for B
class B;   // Forward declare

template<> // Define traits for B. So other classes can use it.
class SubClass_traits<B>
{
    public:
        typedef int mytype;
};

// Define B
class B : public A<B>
{
    // Define mytype in terms of the traits type.
    typedef SubClass_traits<B>::mytype  mytype;
    public:

        B() {}

        void do_action(mytype var) {
                // Do stuff
        }
};

int main(int argc, char** argv)
{
    B myInstance;
    return 0;
} 

answered Mar 16, 2009 at 22:07

Martin York's user avatar

Martin YorkMartin York

253k84 gold badges332 silver badges555 bronze badges

2

You derive B from A<B>, so the first thing the compiler does, once it sees the definition of class B is to try to instantiate A<B>. To do this it needs to known B::mytype for the parameter of action. But since the compiler is just in the process of figuring out the actual definition of B, it doesn’t know this type yet and you get an error.

One way around this is would be to declare the parameter type as another template parameter, instead of inside the derived class:

template<typename Subclass, typename Param>
class A {
    public:
        void action(Param var) {
                (static_cast<Subclass*>(this))->do_action(var);
        }
};

class B : public A<B, int> { ... };

answered Mar 16, 2009 at 21:29

sth's user avatar

sthsth

218k53 gold badges277 silver badges364 bronze badges

Not exactly what you were asking, but you can make action a template member function:

template<typename Subclass>
class A {
    public:
        //Why doesn't it like this?
        template<class V> void action(V var) {
                (static_cast<Subclass*>(this))->do_action();
        }
};

class B : public A<B> {
    public:
        typedef int mytype;

        B() {}

        void do_action(mytype var) {
                // Do stuff
        }
};

int main(int argc, char** argv) {
    B myInstance;
    return 0;
}

answered Mar 16, 2009 at 21:45

John Dibling's user avatar

John DiblingJohn Dibling

98.8k29 gold badges183 silver badges321 bronze badges

You need to use a pointer or a reference as the proper type is not known at this time the compiler can not instantiate it.

Instead try:

void action(const typename Subclass::mytype &var) {
            (static_cast<Subclass*>(this))->do_action();
    }

answered Mar 16, 2009 at 21:17

Andreas Magnusson's user avatar

1

Problem:

You are compiling a C/C++ program using GCC. You get an error message similar to this:

error: invalid use of incomplete type ‘class SomeType’

Solution:

There are multiple possible issues, but in general this error means that GCC can’t find the full declaration of the given class or struct.

The most common issue is that you are missing an #include clause. Find out in which header file the declaration resides, i.e. if the error message mentions class Map, look for something like

class Map {
   // ...
};

Usually the classes reside in header files that are similar to their name, e.g. MyClass might reside in a header file that is called MyClass.h, MyClass.hpp or MyClass.hxx, so be sure to look for those files first. Note that you might also be looking for a type from a library. Often the best approach is to google C++ <insert the missing type here> to find out where it might be located.

Another possible reason is that you have your #include clause after the line where the error occurs. If this is the case, ensure that all required types are included before they are used.

For other reasons, see StackOverflow, e.g. this post

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "dialogadddevice.h"
#include "ui_dialogadddevice.h"
 
DialogAddDevice::DialogAddDevice(int row, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DialogAddDevice)
{
    ui->setupUi(this);
 
 
    /* Метода для инициализации модели,
     * из которой будут транслироваться данные
     * */
    setupModel();
 
    /* Если строка не задана, то есть равна -1,
     * тогда диалог работает по принципу создания новой записи.
     * А именно, в модель вставляется новая строка и работа ведётся с ней.
     * */
    if(row == -1){
        model->insertRow(model->rowCount(QModelIndex()));
        mapper->toLast();
    /* В противном случае диалог настраивается на заданную запись
     * */
    } else {
        mapper->setCurrentModelIndex(model->index(row,0));
    }
 
    createUI();
}
 
DialogAddDevice::~DialogAddDevice()
{
    delete ui;
}
 
/* Метод настройки модели данных и mapper
 * */
void DialogAddDevice::setupModel()
{
    /* Инициализируем модель и делаем выборку из неё
     * */
    model = new QSqlTableModel(this);
    model->setTable(DEVICE);
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->select();
 
    /* Инициализируем mapper и привязываем
     * поля данных к объектам LineEdit
     * */
    mapper = new QDataWidgetMapper();
    mapper->setModel(model);
    mapper->addMapping(ui->HostnameLineEdit, 1);
    mapper->addMapping(ui->IPAddressLineEdit, 2);
    mapper->addMapping(ui->MACLineEdit, 3);
    /* Ручное подтверждение изменения данных
     * через mapper
     * */
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
 
    /* Подключаем коннекты от кнопок пролистывания
     * к прилистыванию модели данных в mapper
     * */
    connect(ui->previousButton, SIGNAL(clicked()), mapper, SLOT(toPrevious()));
    connect(ui->nextButton, SIGNAL(clicked()), mapper, SLOT(toNext()));
    /* При изменении индекса в mapper изменяем состояние кнопок
     * */
    connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(updateButtons(int)));
}
 
/* Метод для установки валидатора на поле ввода IP и MAC адресов
 * */
void DialogAddDevice::createUI()
{
    QString ipRange = "(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])";
    QRegExp ipRegex ("^" + ipRange
                     + "\." + ipRange
                     + "\." + ipRange
                     + "\." + ipRange + "$");
    QRegExpValidator *ipValidator = new QRegExpValidator(ipRegex, this);
    ui->IPAddressLineEdit->setValidator(ipValidator);
 
    QString macRange = "(?:[0-9A-Fa-f][0-9A-Fa-f])";
    QRegExp macRegex ("^" + macRange
                      + "\:" + macRange
                      + "\:" + macRange
                      + "\:" + macRange
                      + "\:" + macRange
                      + "\:" + macRange + "$");
    QRegExpValidator *macValidator = new QRegExpValidator(macRegex, this);
    ui->MACLineEdit->setValidator(macValidator);
}
 
void DialogAddDevice::on_buttonBox_accepted()
{
    /* SQL-запрос для проверки существования записи
     * с такими же учетными данными.
     * Если запись не существует или находится лишь индекс
     * редактируемой в данный момент записи,
     * то диалог позволяет вставку записи в таблицу данных
     * */
    QSqlQuery query;
    QString str = QString("SELECT EXISTS (SELECT " DEVICE_HOSTNAME " FROM " DEVICE
                          " WHERE ( " DEVICE_HOSTNAME " = '%1' "
                          " OR " DEVICE_IP " = '%2' )"
                          " AND id NOT LIKE '%3' )")
            .arg(ui->HostnameLineEdit->text(),
                 ui->IPAddressLineEdit->text(),
                 model->data(model->index(mapper->currentIndex(),0), Qt::DisplayRole).toString());
 
    query.prepare(str);
    query.exec();
    query.next();
 
    /* Если запись существует, то диалог вызывает
     * предупредительное сообщение
     * */
    if(query.value(0) != 0){
        QMessageBox::information(this, trUtf8("Ошибка хоста"),
                                 trUtf8("Хост с таким именем или IP-адресом уже существует"));
    /* В противном случае производится вставка новых данных в таблицу
     * и диалог завершается с передачей сигнала для обновления
     * таблицы в главном окне
     * */
    } else {
        mapper->submit();
        model->submitAll();
        emit signalReady();
        this->close();
    }
}
 
void DialogAddDevice::accept()
{
 
}
 
/* Метод изменения состояния активности кнопок пролистывания
 * */
void DialogAddDevice::updateButtons(int row)
{
    /* В том случае, если мы достигаем одного из крайних (самый первый или
     * самый последний) из индексов в таблице данных,
     * то мы изменяем состояние соответствующей кнопки на
     * состояние неактивна
     * */
    
    ui->previousButton->setEnabled(row > 0);
    ui->nextButton->setEnabled(row < model->rowCount() - 1);
}

I have the following errors trying to use a TFT library function inside my library. My library uses the pointer to an instance of the TFT library in the constructor, as well described there:

Basic C++ programming, how to pass constructor argument into class?

The errors are:

error: invalid use of incomplete type 'class TFT'
_TFTscreen->background(0, 0, 0);

error: forward declaration of 'class TFT'
class TFT;

MESmenu.h:

#ifndef _MESMENU_H_
#define _MESMENU_H_

#include <SPI.h>
#include <SD.h>

class TFT;

class MESmenu{
public:
  MESmenu(TFT* pTFT) : _TFTscreen(pTFT) {};
  void start();
  void execute();
private:
  TFT* _TFTscreen;
};

#endif

MESmenu.cpp:

#include "Arduino.h"
#include "MESmenu.h"

void MESmenu::start(){
  _TFTscreen->background(0, 0, 0);
  _TFTscreen->text("starting menu...", 0, 0);
  //...
}

void MESmenu::execute(){
   //some code...  
}

The Arduino sketch is:

#include <SPI.h>
#include <SD.h>
#include <TFT.h>  // Arduino LCD library
#include <MESmenu.h>  // my library

// --------- TFT LCD ---------
// pin definition for the due
#define sd_cs  7
#define lcd_cs 10
#define dc     9
#define rst    8
TFT TFTscreen = TFT(lcd_cs, dc, rst);

// MES menu class
MESmenu *mainMenu = new MESmenu(&TFTscreen);

void setup() {
  // initialize TFT
  TFTscreen.begin();
  TFTscreen.background(0, 0, 0);
  // set the stroke color to white
  TFTscreen.stroke(255,255,255);
  TFTscreen.fill(255,255,255);
  TFTscreen.setTextSize(2);
  TFTscreen.text("TEST", 0, 0);

  // Start menu
  mainMenu->start();
}

void loop () {
  mainMenu->execute();      
}

The problem is related to the function:

_TFTscreen->background(0, 0, 0);

inside the MESmenu::start() in the .cpp file.

UPDATE:

As suggested by frarugi87 I’ve updated the question with the details of .h and .cpp files.
Those file are in the ArduinolibrariesMESmenu folder.

I try to change

class TFT;

with

#include <TFT.h>

and removed the #include from the main arduino sketch.

This leads to the following errors:

librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: first defined here

librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `PImage::read16(SDLib::File)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/PImage.h:17: first defined here

librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `PImage::read32(SDLib::File)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/PImage.h:17: first defined here

librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `PImage::loadImage(char const*)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/PImage.h:17: first defined here

Forum Updated on Feb 6th

This topic has been deleted. Only users with topic management privileges can see it.

  • C:UsersLorence30Desktoptestmainwindow.h:32: error: invalid use of incomplete type ‘class Ui::MainWindow’ ui->grassyTile
    ^

    why i keep getting this error?

    I have my Q_OBJECT macro inside the MainWindow class.

    *[link text](link url) class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explic[it MainWindow(QWidget *parent = 0);
    ~MainWindow();](link url)

    private slots:
    void changeTile();
    void pushTile();

    private:
    Ui::MainWindow *ui;
    int counter;

    std::array<Tile,1> tile_list
    {
        ui->grassyTile // heres where error coming from
    };
    

    };

  • @Lorence said:

    grassyTile

    What type is that ?

    «use of incomplete type» often means a include file is missing
    or you forwarded a class
    like
    class SomeClass;

    And try to use it in a context where it needs to be fully defined.
    Like adding to some template lists.

    Not sure what you tried to define here ?

    std::array<Tile,1> tile_list <—- ; missing here?
    {
    ui->grassyTile // heres where error coming from
    };

  • grassyTile is of type Tile that is inheriting QLabel

    Not sure what you tried to define here ?
    i dont know how to list intialize an array on constructor so i decided to do it in side a class definition

  • @mrjj said:

    and «tile.h» is included ?
    in mainwindow.h

    do you mean like ?
    std::array<std::string, 2> strings = {{ «a», «b» }};

  • and «tile.h» is included ?

    yes i got all i need included.

    do you mean like ?
    std::array<std::string, 2> strings = {{ «a», «b» }};

    yes, in the mainwindow.cpp i can freely use ui->grassyTile; without error.

  • @Lorence
    Ok so it must be the tile_list statement.

    Would it like
    std::array<Tile,1> tile_list {{ui->grassyTile }};

  • Would it like
    std::array<Tile,1> tile_list {{ui->grassyTile }};

    thanks for the help but i still get the same error

  • @Lorence
    Ok, and you are 100% it knows the tile type here?
    you can declare one over the tile_list and it will like it ?
    Tile *Test;

    One thing I wonder, you say
    std::array<Tile> and not std::array<Tile *) or & so it must make a copy of
    it (the tile). Is that the effect you want?

  • @Lorence
    Hmm it seems its «ui» it do not like.
    Let me test.

  • @mrjj
    ahh, Ui::MainWindow is defined in
    #include «ui_main_window.h»
    which is included in the CPP file so the type is not fully defined so you cannot say
    ui->Somename
    as Ui::MainWindow is not defined yet.

    moving
    #include «ui_main_window.h»
    to the minwin.h file allows it but not sure if it will confuse Qt Creator.

    Also it will complain about not being able to convert Tile to Tile * as list is not pointers and ui->grassyTile will be.

  • ahh, Ui::MainWindow is defined in
    #include «ui_main_window.h»

    didnt think of that, thanks! but new error comes

    View post on imgur.com

  • @Lorence

    Yeah, it tries to construct a new Tile to go into the list.

    Can I ask if you want a list of pointers to tiles you have on screen or
    a list with new Tiles that has nothing to do with those on screen?

  • sorry for the late reply.

    i just want a list of tiles to choose from.

    but QT disabled the copying of QLabel,
    so i really need to have a pointer of tiles?

  • @Lorence
    heh 9 mins is not considered late ;)

    then the list must be pointer type or it will be new ones and not the ones on screen.

    so
    std::array<Tile> should be std::array<Tile *> or std::array<Tile &>
    so its the ones on screen and not new ones
    Yes you must at least use & as it must «point» to the real one.

  • then the list must be pointer type
    yea, i edited my last reply

    it will be new ones and not the ones on screen.

    it is the ones on the screen, there will be a list of tiles on the screen and the user will choose what tiles they want to render

    *so
    std::array<Tile> should be std::array<Tile > or std::array<Tile &>
    so its the ones on screen and not new ones
    Yes you must at least use & as it must «point» to the real one.

    thanks!!!!!!!!

    all my problem is fixed :) I have not coded for weeks and C++ is already kicking me damit

  • @mrjj said:
    ok. Super :)

    and tile_list is the ones to choose from ?

    Dont worry. I programmed c++ for 20 years and it still kicks me ;)

  • and tile_list is the ones to choose from ?

    yes, it is a list of Tile which is inheriting QLabel

    Dont worry. I programmed c++ for 20 years and it still kicks me ;)

    woaaaaa, me is about a year, and started this QT last week, i choose this for my tile engine’s interface from SFML, i still have more ways to go !^_^

  • @Lorence said:
    welcome on board to Qt. its a nice frame work.

    Oh so its some sort of game editor your are making ?

  • welcome on board to Qt. its a nice frame work.

    Yes my first choice is wxwidget and windows form application, but signals and slots mechanism of qt makes me decide to choose qt

    Oh so its some sort of game editor your are making ?
    yes exatcly, like the rpg maker vx ace of steam

  • Forum
  • Beginners
  • Invalid use of incomplete type?

Invalid use of incomplete type?

Here is a simplified version of the problem i’m facing in my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
namespace 
{
  template <class T, class... Types>
   inline constexpr bool is_any_of = (std::is_same_v<T, Types> || ...);


  template<typename T = double,
           typename =
              std::enable_if_t<is_any_of<T,
                                   float, double, long double>>
   >
   class Complex
   {
     public:
       Complex() = default;
       void test();

     private:
       T m_r = T(),
       m_i   = T();

   };

template <typename T>
void Complex<T>::test() 
{} //ERROR HERE

}

int main()
{
Complex a;
}

When I define the test() method outside of the class, the compiler gives me a «invalid use of incomplete type» error, but it works fine when the function is defined inline. I am defining the entire class and the definitions in the same file, so why is it giving me this error?

Last edited on

you can’t just say complex a. you have to give it a type.
complex <double> a; when you make a variable of the type, eg in main there…

Last edited on

jonnin wrote:
you can’t just say complex a. you have to give it a type.

That’s not correct. Omitting the template brackets when the type has a default is perfectly valid in C++17.

My problem is that I am getting an invalid use of incomplete type when I define test() outside of the class. If it were defined inline it works perfectly. I suspect it has something to do with the unnamed typename parameter I am using for SFINAE, but I am not sure why. Can you help me with this?

Last edited on

1
2
3
template <typename T, typename U>
void Complex<T, U>::test() 
{}

@Ganado

Huh, strange. I assumed if a type parameter didn’t have a name it didn’t need to be named in the member function definition outside of the class. This seems quite strange that you can leave it unnamed inside the class definition, but you have to give it a name outside. This means that Complex<T> is valid in the class but not outside of it. Weird. Anyway, thank you. Fixed.

Last edited on

To be honest I’m not sure of the formal rules here, but my gut feeling would say that you can’t ignore one of the template parameters in the definition of the function template.

By the way, it seems you’re trying to restrict the use of the Complex type to only be float, double, or long double, right?
A static_assert might be simpler here. And I imagine C++20 Concepts would help here and supersede static_assert, although I have not used Concepts yet in practice.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <type_traits>

template <typename T = double>
class Complex {
    static_assert(std::is_floating_point<T>::value);

  public:
    Complex() = default;
};

struct Bogus { };

int main()
{
Complex a;
Complex<float> b;
//Complex<int> c; // error
//Complex<Bogus> c; // error
//Complex<float, float> c; // error
}

Or even better:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <type_traits>

template <typename T = double>
class Complex {
    static_assert(std::is_floating_point<T>::value);

  public:
    Complex() = default;
};

struct Bogus { };

int main()
{
Complex a;
Complex<float> b;
//Complex<int> c; // error
//Complex<Bogus> d; // error
//Complex<float, float> e; // error
}

Last edited on

Ganado wrote:
To be honest I’m not sure of the formal rules here, but my gut feeling would say that you can’t ignore one of the template parameters in the definition of the function template.

It seems that the rules are even weirder if you have an object of type Complex passed as a parameter or a return value. Here is what the out-of-class definition would look like:

1
2
3
template <typename T, typename U>
Complex<T> Complex<T, U>::test(Complex<T>&) 
{}

So in the case of a parameter or a return value, you have to use Complex<T> as normal. Complex<T,U> is only for the disambiguation of the member function. If you try to use Complex<T,U> as a return value or a parameter the compiler complains. Weird!

Topic archived. No new replies allowed.

Автор Тема: invalid use of incomplete type (решено)  (Прочитано 24742 раз)
theorist

Гость


здравствуйте!
оказался в тупике, хотя решение, наверняка, насколько простое, что сам, наверное, буду долго смеяться …

итак, пытаюсь в Qt Creator сделать программу, а вместо неё получаю следующее:

…/mainwindow.cpp:38: ошибка: invalid use of incomplete type ‘struct TableModel’
…/mainwindow.h:11: ошибка: forward declaration of ‘struct TableModel’
…/mainwindow.cpp:39: ошибка: нет подходящей функции для вызова ‘QTableView::setModel(TableModel*&)’

сам код такой:


//mainwindow.cpp

#include <QTableView>

#include «mainwindow.h»
#include «tablemodel.h»

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
createCentralWdgt();

}

void MainWindow::createCentralWdgt()
{
tableView = new QTableView();
tableModel = new TableModel();
tableView->setModel(tableModel);
setCentralWidget(tableView);
}


//mainwindow.h

#include <QtGui/QMainWindow>

class QTableView;
class TableModel;

class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);

private:

QTableView *tableView;
TableModel *tableModel;

void createCentralWdgt();

};


//tablemodel.h

#include <QAbstractTableModel>

class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
TableModel(QObject* = 0);
int rowCount(const QModelIndex& = QModelIndex()) const;
int columnCount(const QModelIndex& = QModelIndex()) const;
QVariant data(const QModelIndex&, int = Qt::DisplayRole) const;
QVariant headerData(int, Qt::Orientation, int = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex&) const;
bool insertRows(int, int, const QModelIndex& = QModelIndex());
bool removeRows(int, int, const QModelIndex& = QModelIndex());
bool insertColumns(int, int, const QModelIndex& = QModelIndex());
bool removeColumns(int, int, const QModelIndex& = QModelIndex());

};


//tablemodel.cpp

#include «tablemodel.h»

TableModel::TableModel(QObject *parent) : QAbstractTableModel(parent) {…}
int TableModel::rowCount(const QModelIndex &parent) const {…}
int TableModel::columnCount(const QModelIndex &parent) const {…}
QVariant TableModel::data(const QModelIndex &index, int role) const {…}
QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const {…}
Qt::ItemFlags TableModel::flags(const QModelIndex &index) const {…}
bool TableModel::insertRows(int position, int rows, const QModelIndex &index) {…}
bool TableModel::removeRows(int position, int rows, const QModelIndex &index) {…}
bool TableModel::insertColumns(int position, int columns, const QModelIndex &index) {…}
bool TableModel::removeColumns(int position, int columns, const QModelIndex &index) {…}

прошу помощи  Непонимающий

« Последнее редактирование: Июнь 02, 2010, 19:43 от theorist »
Записан
ритт

Гость


а весь файл tablemodel.h можно?


Записан
theorist

Гость


а весь файл tablemodel.h можно?

конечно, хотя, в принципе, он практически соответствует уже выложенному. вот:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QAbstractTableModel>

class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
TableModel(QObject* = 0);
int rowCount(const QModelIndex& = QModelIndex()) const;
int columnCount(const QModelIndex& = QModelIndex()) const;
QVariant data(const QModelIndex&, int = Qt::DisplayRole) const;
QVariant headerData(int, Qt::Orientation, int = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex&) const;
bool insertRows(int, int, const QModelIndex& = QModelIndex());
bool removeRows(int, int, const QModelIndex& = QModelIndex());
bool insertColumns(int, int, const QModelIndex& = QModelIndex());
bool removeColumns(int, int, const QModelIndex& = QModelIndex());
private:
QList<QStringList> array;
};

#endif // MAINWINDOW_H


Записан
Rcus

Гость


Copy-paste умеет не только ракеты ронять.
Copy-paste умеет не только ракеты ронять

/* смотрит на include guards */


Записан
theorist

Гость


Copy-paste умеет не только ракеты ронять.
Copy-paste умеет не только ракеты ронять

/* смотрит на include guards */

спасибо! я же говорил, что сам буду смеяться  Смеющийся


Записан
theorist

Гость


Не понял, прошу объяснить где ошибка (я ее не нашел)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#endif // MAINWINDOW_H

а файл называется tablemodel.h. правда, смешно? Веселый


Записан
ритт

Гость


почему и просил весь файл…


Записан
theorist

Гость


почему и просил весь файл…

спасибо за наводку, Константин! но без дополнительной подсказки я бы, наверное, ни за что не догадался бы, что причина проблемы кроется именно в директивах препроцессора. впредь буду обращать на них больше внимания.

думаю, что тему лучше перенести в раздел «Программирование: C/C++»


Записан
Igors


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#endif // MAINWINDOW_H

а файл называется tablemodel.h. правда, смешно? Веселый

Спасибо, теперь понял  Улыбающийся


Записан
Mityai

Гость


Ребят, спасибо большое за эту тему! Я наконец-то понял как QTableView связать с QAbstractTableModel Смеющийся


Записан
dee

Гость


Была аналогичная проблема.

Оказалось, при изменении objectName кнопки на форме (при магическом стечении обстоятельств по радиусу кривизны рук) была переименована не кнопка, а вся форма, в результате чего вылетало такое сообщение об ошибке.

Мораль:
БУДЬ ВНИМАТЕЛЕН!


Записан

InvalidConversion is a dummy class: it’s declared but not defined.
ArduinoJson uses this class to trigger a compilation error with a distinctive pattern.

Thanks to this class, when you try to perform an invalid conversion, you get an error like this one:

In file included from .../ArduinoJson/Array/ArrayIterator.hpp:8:0,
                 from .../ArduinoJson/Array/ArrayRef.hpp:8,
                 from .../ArduinoJson.hpp:17,
                 from .../ArduinoJson.h:9,
                 from MyProgram.ino:9:
.../ArduinoJson/Variant/JsonVariant.hpp: In instantiation of 'typename ArduinoJson6180_91::enable_if<((! ArduinoJson6180_91::is_same<T, char*>::value) && (! ArduinoJson6180_91::is_same<T, char>::value)), T>::type ArduinoJson6180_91::JsonVariantConst::as() const [with T = ArduinoJson6180_91::ObjectRef; typename ArduinoJson6180_91::enable_if<((! ArduinoJson6180_91::is_same<T, char*>::value) && (! ArduinoJson6180_91::is_same<T, char>::value)), T>::type = ArduinoJson6180_91::ObjectRef]':
MyProgram.ino:37:44:   required from here
.../ArduinoJson/Variant/JsonVariant.hpp:251:34: error: invalid use of incomplete type 'class ArduinoJson6180_91::InvalidConversion<ArduinoJson6180_91::JsonVariantConst, ArduinoJson6180_91::ObjectRef>'
     return Converter<T>::fromJson(*this);
            ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
In file included from .../ArduinoJson/Variant/JsonVariant.hpp:14:0,
                 from .../ArduinoJson/Array/ArrayIterator.hpp:8,
                 from .../ArduinoJson/Array/ArrayRef.hpp:8,
                 from .../ArduinoJson.hpp:17,
                 from .../ArduinoJson.h:9,
                 from MyProgram.ino:9:
.../ArduinoJson/Variant/Converter.hpp:14:7: note: declaration of 'class ArduinoJson6180_91::InvalidConversion<ArduinoJson6180_91::JsonVariantConst, ArduinoJson6180_91::ObjectRef>'
 class InvalidConversion;  // Error here? See https://arduinojson.org/v6/invalid-conversion/
       ^~~~~~~~~~~~~~~~~

As you can see, InvalidConversion is a template class that takes two arguments. The first is the original type, and the second is the type it’s converted to. Unfortunately, the error shows the internal names instead of the public names.

For example, after removing the namespaces in the error above, it says:

invalid use of incomplete type 'class InvalidConversion<JsonVariantConst, ObjectRef>'

The internal name JsonVariantConst corresponds to JsonVariantConst, and ObjectRef corresponds to JsonObject. Indeed, converting from JsonVariantConst to JsonObject is invalid because it would convert a read-only reference to a read-write reference.

To fix this issue, you must convert the read-only reference to a read-only reference. In our example, it means we must replace JsonObject with JsonObjectConst.
So, somewhere in the program, there is a statement like variant.as<JsonObject>() or JsonObject obj = variant that must be changed into variant.as<JsonObjectConst>() or JsonObjectConst obj = variant.

Понравилась статья? Поделить с друзьями:
  • Error invalid transaction termination
  • Error invalid token error description token is incorrect перевод
  • Error invalid texture index 3ds max
  • Error invalid terms in product
  • Error invalid suffix x on integer constant