Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.52/21: Рейтинг темы: голосов - 21, средняя оценка - 4.52
30 / 8 / 2
Регистрация: 20.08.2011
Сообщений: 615

Как узнать количество аргументов конструктора?

13.02.2015, 15:33. Показов 4749. Ответов 46
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день.
Как на этапе компиляции узнать, сколько аргументов имеет конструктор некоторого класса?
Нужно в шаблонной функции по переданному классу Type определить количество:
1. Если аргументов 1 шт, то
C++ (Qt)
1
Type *object = new Type(this);
2. Если аргументов 2 шт, то
C++ (Qt)
1
Type *object = new Type(this, "это строка");
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
13.02.2015, 15:33
Ответы с готовыми решениями:

Как узнать количество аргументов в команде/строке?
Есть команда, или можно сказать строка: /hello 144 12 155 Нужно узнать сколько аргументов в данной строке. В данном случае 3: 144, 12,...

Узнать количество пеледаваемых в функцию аргументов
Я про функсию с пелеменным колисеством алгументов.

Ошибка в списке аргументов конструктора
Добрый вечер, пишу программу по строкам с помощью классов. И вот выдаёт такую непонятню ошибку: #include <iostream> ...

46
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
14.02.2015, 01:42
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от hoggy Посмотреть сообщение
тн
Можете прокомментировать 6 пост код? Где там магия происходит не пойму
0
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
14.02.2015, 02:54
ТС, в классе объяви приватный static элемент в котором укажи сколько параметров в конструкторе надо юзать(метод по его получению публик).
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
14.02.2015, 04:53
Цитата Сообщение от DU Посмотреть сообщение
я как раз таки и указал что я не знаю как это определить. поэтому и спрашиваю.
давайте упростим условия: определителю подсовывают только классы с одним нешаблонным
конструктором, у которого конечное количество аргументов и нет аргументов по умолчанию, нет
конструкторов с эллипсисами (если такие возможны) типы аргументов по прежнему неизвестны.
Если с таким условием, то вот.
Кликните здесь для просмотра всего текста
C++
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
#include <iostream>
#include <type_traits>
 
template <typename T, typename ...Args>
struct check_ctor_sig
{
private:
    struct Checker : T
    {
        explicit Checker(Checker const &);
        explicit Checker(Checker &&);
 
        using T::T;
    };
    template <typename U>
    static std::integral_constant<bool, !!sizeof(::new U{Args()...})> SFINAE(U *);
    template <typename U>
    static std::integral_constant<bool, false> SFINAE(...);
 
public:
    enum { value = decltype(SFINAE<Checker>(nullptr))::value };
};
 
template <typename T>
struct ctor_args_count
{
    template <typename Arg>
    static constexpr size_t count(Arg const &)
    {
        return check_ctor_sig<T, Arg>::value;
    }
    template <typename Arg, typename ...Args>
    static constexpr size_t count(Arg const &, Args const & ...args)
    {
        return check_ctor_sig<T, Arg, Args...>::value ? sizeof...(args) + 1 : count(args...);
    }
    struct Fake
    {
        template <typename U> operator U() const;
    };
    enum
    {
        value = count(Fake(), Fake(), Fake(), Fake(), Fake(), Fake(), Fake())
    };
};
 
struct A
{
    A(int);
};
struct B
{
    B(int, std::string const &);
};
struct C
{
    C(int, double, std::string const &);
};
struct D
{
    D(char, A, B const &, C &&);
};
struct E
{
    E();
};
 
int main()
{
    std::cout << "Ctor args count for A(): " << ctor_args_count<A>::value << std::endl;
    std::cout << "Ctor args count for B(): " << ctor_args_count<B>::value << std::endl;
    std::cout << "Ctor args count for C(): " << ctor_args_count<C>::value << std::endl;
    std::cout << "Ctor args count for D(): " << ctor_args_count<D>::value << std::endl;
    std::cout << "Ctor args count for E(): " << ctor_args_count<E>::value << std::endl;
}

Правильно работает только в clang, в gcc - баг с инициализацией, в VS - недоделанные constexpr и brace-initialization. Демо. Максимальное кол-во параметров - 7 (но это можно увеличить).

Добавлено через 9 минут
А, да. С неконстантными ссылками в параметрах - не работает. Лень разбираться. Все равно это just for fun написано.
7
30 / 8 / 2
Регистрация: 20.08.2011
Сообщений: 615
14.02.2015, 10:21  [ТС]
Цитата Сообщение от Enno Посмотреть сообщение
ТС, в классе объяви приватный static элемент в котором укажи сколько параметров в конструкторе надо юзать(метод по его получению публик).
Неудобно. Это нужно делать в каждом классе.

В общем сейчас у меня функция такая:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
template<typename Type>
Type* MainWindow::_addTab(const QString &id, const QString &title)
{
    ...
    ЕСЛИ КОНСТРУКТОР ИМЕЕТ 2 АРГУМЕНТА, ТО:
    Type *tab = new Type(_db, ui->tabWidget);
    ИНАЧЕ:
    Type *tab = new Type(ui->tabWidget);
    ...
    return tab;
}
Можете ее переписать с проверкой кол-ва аргументов?
Из первых постов не понятно логика проверки. Зачем структуры? Зачем пустые структуры? Зачем функция, которая возвращает всегда true (false)?
0
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
14.02.2015, 11:10
Цитата Сообщение от [progeR] Посмотреть сообщение
Неудобно. Это нужно делать в каждом классе.
Лолка, в каждом классе ты и так пишешь конструктор, дополнительное одно значение инициализировать уже трудно после этого?
0
30 / 8 / 2
Регистрация: 20.08.2011
Сообщений: 615
14.02.2015, 11:15  [ТС]
Не каждому классу требуется объект базы данных.
Поясняю, переменная _db это объект класса QSqlDatabase. ui->tabWidget - это объект класса QTabWidget.
0
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
14.02.2015, 11:22
Цитата Сообщение от [progeR] Посмотреть сообщение
ЕСЛИ КОНСТРУКТОР ИМЕЕТ 2 АРГУМЕНТА, ТО:
Позвольте конкретизировать ваше выражение в псевдокоде:
У КЛАССА Type ИМЕЕТСЯ КОНСТРУКТОР С 2 АРГУМЕНТАМИ, ТО:
0
30 / 8 / 2
Регистрация: 20.08.2011
Сообщений: 615
14.02.2015, 11:32  [ТС]
А что не понятно?
Если конструктор у переданного класса Type имеет два аргумента, то создать объект таким образом:
C++ (Qt)
1
Type *tab = new Type(_db, ui->tabWidget);
Если только один аргумент, то создать объект таким образом:
C++ (Qt)
1
Type *tab = new Type(ui->tabWidget);
Передаваемые классы в эту шаблонную функцию имеют конструкторы вида:
Code
1
SomeClassWithSqlSupport::SomeClassWithSqlSupport(const QsqlDatabase &db, QWidget *parent)
либо
Code
1
SomeSimpleClass::SomeSimpleClass(QWidget *parent)
где названия классов SomeClassWithSqlSupport и SomeSimpleClass взяты для примера. Всех классов будет в сумме будет с десяток.

Вот и нужно определить - данному классу нужно передавать объект базы данных, или это простой класс.
Надеюсь понятно объяснил.
0
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
14.02.2015, 11:48
Цитата Сообщение от [progeR] Посмотреть сообщение
А что не понятно?
У класса может быть несколько конструкторов, поэтому по логике необходим факт наличия конструктора с 2 переменными.
Можно ли добавить конструктор с 1 аргументов в 2, но первый аргумент игнорить и вызывать конструктор с 1 аргументом? А так SFINAE может только помочь.
0
30 / 8 / 2
Регистрация: 20.08.2011
Сообщений: 615
14.02.2015, 11:51  [ТС]
Цитата Сообщение от Enno Посмотреть сообщение
Можно ли добавить конструктор с 1 аргументов в 2, но первый аргумент игнорить и вызывать конструктор с 1 аргументом?
Можно, только это костыль.

И как тогда sfinae будет выглядеть с учетом дополнений (см. выше посты)?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
14.02.2015, 12:00
Цитата Сообщение от DrOffset Посмотреть сообщение
struct Fake
* * {
* * * * template <typename U> operator U() const;
* * };
* * enum
* * {
* * * * value = count(Fake(), Fake(), Fake(), Fake(), Fake(), Fake(), Fake())
* * };
Супер!

Там всякие constexpr, с которыми студия не дружит не очень то и нужны.
Код можно облегчить, тогда на разных компиляторах заработает
0
30 / 8 / 2
Регистрация: 20.08.2011
Сообщений: 615
14.02.2015, 12:43  [ТС]
Так как сделать?

Добавлено через 4 минуты
Да, и кстати всякие стат. константы в классе нифига не работают. Типа: static constexpr bool IS_SQL = true; или static constexpr bool IS_SQL = false;

Добавлено через 46 секунд
Как не разделял конструкторы, так и не разделяет.
0
 Аватар для DiffEreD
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
14.02.2015, 13:05
[progeR], от себя могу предложить еще такой вариант, через enable_if:
C++
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
#include <iostream>
#include <type_traits>
#include <memory>
 
struct A
{
    int val;
    A(int v) : val(v) {}
    void print() const {std::cout << val << "\n";}
};
 
struct B
{
    int val;
    std::string str;
    B(int v, std::string const &s) : val(v), str(s) {}
    void print() const {std::cout << val << ", " << str << "\n";}
};
 
namespace detail
{
 
template <class T, typename std::enable_if<std::is_constructible<T, int>::value>::type* = nullptr>
std::shared_ptr<T> makeT(int val, const std::string &str)
{
    return std::make_shared<T>(val);
}
 
template <class T, typename std::enable_if<std::is_constructible<T, int, std::string>::value>::type* = nullptr>
std::shared_ptr<T> makeT(int val, const std::string &str)
{
    return std::make_shared<T>(val, str);
}
 
}
 
template <typename T>
std::shared_ptr<T> make_expl(int val = 0, const std::string &str = "")
{
    return detail::makeT<T>(val, str);
}
 
int main()
{
    auto pt = make_expl<A>(42, "Hello");
    pt->print(); // 42
 
    auto pt2 = make_expl<B>(84, "world");
    pt2->print(); // 84, world
}
3
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
14.02.2015, 13:48
Цитата Сообщение от hoggy Посмотреть сообщение
Там всякие constexpr, с которыми студия не дружит не очень то и нужны.
Согласен, что не нужны, но даже без них, студия у меня отказалась работать. Главная проблема, что алгоритм путает конструктор с одним параметром, с конструкторами копирования и перемещения. В clang у меня получилось их убрать из рассмотрения, а в остальных компиляторах - нет. Если будут идеи как это улучшить, с удовольствием посмотрю.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
14.02.2015, 13:54
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Можете прокомментировать 6 пост код? Где там магия происходит не пойму
Магией называют различные трюки на шаблонах,
в частности использование техник sfinae.

Добавлено через 4 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
Согласен, что не нужны, но даже без них, студия у меня отказалась работать. Главная проблема, что алгоритм путает конструктор с одним параметром, с конструкторами копирования и перемещения.
Можно попробовать порезать их при помощи sfinae (std::enable_if для всех, кто не T, где T - наш класс)

Цитата Сообщение от DrOffset Посмотреть сообщение
В clang у меня получилось их убрать из рассмотрения, а в остальных компиляторах - нет. Если будут идеи как это улучшить, с удовольствием посмотрю.
Я посмотрю, что можно сделать и обязательно отпишусь о результатах)
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
14.02.2015, 14:02
Цитата Сообщение от hoggy Посмотреть сообщение
Можно попробовать порезать их при помощи sfinae (std::enable_if для всех, кто не T, где T - наш класс)
Тогда не будет работать приведение (если, конечно, я правильно тебя понял) и как результат всегда fail при подстановке. Это я пробовал. Если оператор приведения будет выглядеть так,
C++
1
2
3
4
5
    struct Fake
    {
        template <typename U> 
        operator typename std::enable_if<!std::is_same<U,  T>::value, T>::type() const;
    };
то он перестанет срабатывать. По той же причине, почему не работает автовывод аргументов при появлении непрямой зависимости от шаблонного параметра.
Если же ты о чем-то другом говорил, то хотел бы глянуть на пример.
0
30 / 8 / 2
Регистрация: 20.08.2011
Сообщений: 615
14.02.2015, 14:06  [ТС]
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
In file included from MainWindow.cpp:1:0:
MainWindow.h: In instantiation of 'T* MainWindow::make_expl(QWidget*, const QSqlDatabase&) [with T = ItemsUpdater]':
MainWindow.cpp:72:47:   required from 'Type* MainWindow::_addTab(const QString&, const QString&) [with Type = LogViewer; bool withDb = false]'
MainWindow.h:80:82:   required from here
MainWindow.h:71:35: error: no matching function for call to 'MainWindow::makeT(QWidget*&, const QSqlDatabase&)'
         return makeT<T>(parent, db);
                                   ^
MainWindow.h:71:35: note: candidates are:
MainWindow.h:57:8: note: template<class T, typename std::enable_if<std::is_constructible<T, QWidget>::value>::type* <anonymous> > T* MainWindow::makeT(QWidget*, const QSqlDatabase&)
     T* makeT(QWidget *parent, const QSqlDatabase &db)
        ^
MainWindow.h:57:8: note:   template argument deduction/substitution failed:
MainWindow.h:56:99: error: no type named 'type' in 'struct std::enable_if<false, void>'
     template <class T, typename std::enable_if<std::is_constructible<T, QWidget>::value>::type* = nullptr>
                                                                                                   ^
MainWindow.h:56:99: note: invalid template non-type parameter
MainWindow.h:63:8: note: template<class T, typename std::enable_if<std::is_constructible<T, QSqlDatabase, QWidget>::value>::type* <anonymous> > T* MainWindow::makeT(QWidget*, const QSqlDatabase&)
     T* makeT(QWidget *parent, const QSqlDatabase &db)
        ^
MainWindow.h:63:8: note:   template argument deduction/substitution failed:
MainWindow.h:62:113: error: no type named 'type' in 'struct std::enable_if<false, void>'
     template <class T, typename std::enable_if<std::is_constructible<T, QSqlDatabase, QWidget>::value>::type* = nullptr>
Ваш метод не работает...

Сами функции компилируются, но только, если они нигде не используются.
Вот что у меня:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private:
template <class T, typename std::enable_if<std::is_constructible<T, QWidget>::value>::type* = nullptr>
    T* makeT(QWidget *parent, const QSqlDatabase &db)
    {
        return new T(parent);
    }
 
    template <class T, typename std::enable_if<std::is_constructible<T, QSqlDatabase, QWidget>::value>::type* = nullptr>
    T* makeT(QWidget *parent, const QSqlDatabase &db)
    {
        return new T(db, parent);
    }
 
    template <typename T>
    T* make_expl(QWidget *parent, const QSqlDatabase &db)
    {
        return makeT<T>(parent, db);
    }
В файле CPP:
C++ (Qt)
1
2
3
4
5
template<typename Type, bool withDb>
Type* MainWindow::_addTab()
{
    make_expl<Type>(ui->tabWidget, _db);
}
0
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
14.02.2015, 15:29
Цитата Сообщение от [progeR] Посмотреть сообщение
Можно, только это костыль.
Лучше прямой костыль, чем кривая нога. Попробуй пока так.
1
30 / 8 / 2
Регистрация: 20.08.2011
Сообщений: 615
14.02.2015, 15:49  [ТС]
Цитата Сообщение от Enno Посмотреть сообщение
Лучше прямой костыль, чем кривая нога. Попробуй пока так.
Что-то у меня не получается.
Значит делаю так: в public области в классах пишу это:
C++
1
static constexpr bool IS_SQL = true;
или это соответственно:
C++
1
static constexpr bool IS_SQL = false;
Далее в объекте главного окна в его методе пишу это:
C++ (Qt)
1
2
3
4
5
6
7
template<typename Type>
Type* MainWindow::_addTab()
{
    ...
    Type *tab = Type::IS_SQL ? new Type(_db, ui->tabWidget) : new Type(ui->tabWidget);
    ...
}
Не компилируется, т.к. не видит, как я понимаю, оператора if-else.
0
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
14.02.2015, 15:51
Цитата Сообщение от [progeR] Посмотреть сообщение
Type *tab = Type::IS_SQL ? new Type(_db, ui->tabWidget) : new Type(ui->tabWidget);
Перепиши с использованием if/else. Также желательно сразу показывать что компилятор говорит.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
14.02.2015, 15:51

Неправильная передача аргументов конструктора класса
Есть несколько конструкторов: student(char* name, char* group, int course, int marks){ strcpy(FIO, name); strcpy(this-&gt;group,...

Изменение параметров конструктора без аргументов
Как в конструкторе без параметров изменить значения из функции main?

Как узнать имя конструктора объекта
Всем доброго времени суток. Продолжаю разбираться с ООП в JS. Возникла проблема: хочу написать метод в базовом классе, который будет...

Три конструктора с разным количеством аргументов, какой использовать?
В 1-ом классе 3 конструктора, которые имеют разное кол-во аргументов(3 арг, 6 и 11). Теперь во 2-ом классе создан объект из 1-го, в...

Странное расположение в памяти аргументов функции с неизвестным количество аргументов
Не могу понять, почему такая программа не работает, выдавая segmentation fault после распечатки первой строки: void makeArr(char *str,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Программное добавление префикса в нумерацию документов
Maks 27.10.2026
Задача: Программно добавить префикс в нумерацию документов в самописной конфигурации на БСП (помощь начинающему коллеге). Решение: В модуле объекта документа размещен следующий код: Процедура. . .
После закрытия оутлука продолжает висеть процесс в диспетчере задач
Maks 27.10.2026
С недавнего времени в продакшене возникла проблема: при закрытии оутлука в диспетчере задач продолжал висеть процесс outlook. exe. Проблема возникла после установки MS Office 2021 LTSC на машинах, под. . .
Baragoz - DPS/HPS бот для WoW 3.3.5a, многоязычный
AmbA 26.10.2026
Хотите ещё ботов? У меня есть один! А я пока отдохну от него. https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=12062&stc=1&d=1793007952 Инструкция внутри. https:/ / youtu. be/ VpfFZSUDGnQ. . .
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru