Форум программистов, компьютерный форум, киберфорум
Наши страницы

C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 5.00
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,552
#1

Перенаправление указателя при перегрузке оператора в variadic template - C++

18.04.2015, 16:19. Просмотров 1439. Ответов 35
Метки нет (Все метки)

Есть вот такой вот код (сделан в vs2014):
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
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "windows.h"
#include "windowsx.h"
 
using namespace std;
 
int Cur = 0;
 
struct var
{
    int ps; // pointer size
    union
    {
        bool b;
        int i;
        PVOID vp;
        char *pc;
        void *pv;
        int *pi;
        double *pd;
        operator bool & ()
        {
            cout << "### Bool overload operator" << endl;
            return b;
        }
        operator int & ()
        {
            cout << "### Int overload operator" << endl;
            return i;
        }
        operator int * ()
        {
            cout << "### POINTER Int overload operator" << endl;
            return pi;
        }
        operator double * ()
        {
            cout << "### POINTER Double overload operator" << endl;
            return pd;
        }
        operator double & ()
        {
            cout << "### Double overload operator" << endl;
            return pd[0]; // вот тут вопрос
        }
        operator PVOID & ()
        {
            cout << "### PVOID overload operator" << endl;
            return vp;
        }
        operator char * ()
        {
            cout << "### Char[] overload operator" << endl;
            return pc;
        }
        operator void * ()
        {
            cout << "### Void[] overload operator" << endl;
            return pv;
        }
    }d;
};
var **v;
 
template<typename Result, typename... Args>
void call(void * fun, Result& r, Args ... args)
{
    using func_type = Result(_cdecl *)(Args...); // прототип функции
    r = ((func_type)fun) (args...); // вызов функции
}
 
int SomeFunc2();
 
int _tmain(int argc, _TCHAR* argv[])
{
    if(SomeFunc2()==0)
        cout << "End Programm" << endl;
    _getch();
    return 0;
}
 
int SomeFunc2()
{
    int res = 0;
    int b = 2;
    v = new var*[b];//динамическая матрица
    v[0] = new var[10];
    v[1] = new var[6];
    v[0][0].d.i = 10;
    v[0][1].d.pc = new char[100];
    v[0][2].d.pc = new char[100];
    v[0][3].d.vp = NULL;
    v[0][4].d.vp = NULL;
    v[0][5].d.i = NULL;
    v[0][6].d.i = 100;
    v[0][7].d.pc = new char[100];
    v[0][8].d.i = 99;
    v[0][9].d.i = 10;
    //
    v[1][0].d.i = 6;
    v[1][1].d.i = NULL;
    v[1][2].d.pd = new double[10];
    v[1][3].d.pc = new char[100];
    v[1][4].d.i = 99;
    v[1][5].d.i = 10;
    //
    strcpy_s(v[0][1].d.pc, v[0][8].d.i, "msvcr120.dll");
    //
    for (int i = 0; i < 10; i++)
    {
        v[1][2].d.pd[i] = NULL;
    }
    strcpy_s(v[1][3].d.pc, v[1][4].d.i, "123.32");
    // test call with pd[0]
    v[1][2].d.pd[0] = atof(v[1][3].d.pc);
    cout << "Test atof result: " << v[1][2].d.pd[0] << endl;
    v[1][2].d.pd[0] = 0;
    //
    cout << "Library Name: " << v[0][1].d.pc << endl;
    int go = 0;
    v[0][3].d.vp = GetModuleHandleA(v[0][1].d);
    if (!v[0][3].d.vp)
    {
        cout << "Library -NOT- found, try load..." << endl;
        v[0][3].d.vp = LoadLibraryA(v[0][1].d);
        if (!v[0][3].d.vp)
            cout << "Library -NOT- loaded" << endl;
        else
        {
            cout << "Library loaded" << endl;
            go = 2;
        }
    }
    else
    {
        cout << "Library found" << endl;
        go = 1;
    }
    if (go != 0)
    {
        strcpy_s(v[0][2].d.pc, v[0][8].d.i, "atof");//_itoa_s
        cout << "Function Name: " << v[0][2].d.pc << endl;
        v[0][4].d.vp = GetProcAddress((HMODULE)v[0][3].d.vp, v[0][2].d.pc);
        if (!v[0][4].d.vp)
            cout << "Function -NOT- found" << endl;
        else
        {
            cout << "Function found, try call..." << endl;
            //call(v[0][4].d.vp, v[1][1].d, v[1][2].d, v[1][3].d, v[1][4].d, v[1][5].d);
            //call(v[0][4].d.vp, v[1][2].d.pi[0], v[1][3].d);
            //call(v[0][4].d.vp, v[1][2].d, v[1][3].d);
            //v[1][1].d.i = atoi(v[1][3].d.pc);
            Cur = 0;
            //v[1][2].d.pd[Cur] = atof(v[1][3].d.pc); // double
            //call(v[0][4].d.vp, v[1][2].d.pd[Cur], v[1][3].d);
            call(v[0][4].d.vp, v[1][2].d, v[1][3].d);
            if (v[1][2].d.pd[Cur] == NULL)
                cout << "Failed result, error: " << endl;
            else
            {
                //char fStr[100] = "";
                //sprintf_s(fStr, sizeof(fStr), "%f", v[1][2].d.pd[Cur]);
                cout << "Returned DOUBLE PTR[" << Cur << "]: " << v[1][2].d.pd[Cur] << endl;
            }
        }
        if (go == 2)
        {
            FreeLibrary((HMODULE)v[0][3].d.vp);
            cout << "Library cleaned" << endl;
        }
    }
    delete[]v[0][7].d.pc;
    delete[]v[0][2].d.pc;
    delete[]v[0][1].d.pc;
    delete[]v[0];
    delete[]v[1][3].d.pc;
    delete[]v[1][2].d.pd;
    delete[]v[1];
    delete[]v;
    return res;
}
Я не хочу вводить в вложенный юнион перменную double, вместо этого хочу чтоб нужная переменная вызывалась из указателя.

Как видится всё это... Вот это должно по сути сработать... (пока что статически написан "0", в будущем конешно хотелось бы тоже поправить, чтоб можно было изменить, для этого int Cur хотел использовать)
C++
1
2
3
4
5
operator double & ()
        {
            cout << "### Double overload operator" << endl;
            return pd[0]; // вот тут вопрос
        }
При выполении программы правильно работает только тест, где явно указано где что брать:
C++
1
v[1][2].d.pd[0] = atof(v[1][3].d.pc);
Потом уже при "не явном вызове" уже происходит ошибка, и получается что перегруженный оператор не срабатывает.
C++
1
call(v[0][4].d.vp, v[1][2].d, v[1][3].d);
Я так понимаю что шаблон всё равно ссылается на адрес v[1][2].d, а ведь я предполагал, что перегруженный оператор должен перенаправить адрес в указатель pd[0].

И ещё, смежный вопрос, как в самом шаблоне проверить какой тип требуется и адрес.
Т.е. хотелось бы чтоб в шаблоне можно было тоже следить за поведением переменных.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.04.2015, 16:19
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Перенаправление указателя при перегрузке оператора в variadic template (C++):

Variadic templates, или variadic constructor в шаблоне, или прочие извращения - C++
Здравствуйте. Есть такое Wrapper&lt;Obj&gt; w; Wrapper - обертка над объектом того класса, который ему скормят (в данном случае - Obj)....

Встроенный оператор C++ откликается при перегрузке - C++
Вот возникает ошибочка, кажется я понимаю почему List&lt;int&gt; abc; abc &lt;&lt; 1 &lt;&lt; 5; Имеется у списка собственно LIST&amp; operator...

Ошибка при комилировании. Cannot use template 'texnika<T>' without specifying specialization parameters - C++ Builder
Выходит вот такая ошибка: Unit1.cpp(34): E2102 Cannot use template 'texnika&lt;T&gt;' without specifying specialization parameters ...

Передача в метод по перегрузке оператора указателя на объект - C++
У нас есть массив указателей на базовый класс STRING **ptr = new STRING* ; for (int i = 0; i&lt;size; ++i) { ...

Variadic template - C++
Добрый день, господа. Будьте добры, помогите кто может. Есть у меня шаблонный класс template&lt;typename ... Types&gt; Class :...

recursion with variadic template - C++
#define NOT_COMPILE 1 #if NOT_COMPILE // так не компилится template &lt;class Type, unsigned int head, unsigned int ... rest &gt; ...

35
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,552
22.04.2015, 22:36  [ТС] #16
Цитата Сообщение от DrOffset Посмотреть сообщение
в левой части выражения был требуемый тип. А там у тебя шаблон.
Нет не так, по крайней мере я так думаю. Одно дело у тебя какой то там пустой шаблон, а другое дело когда аргументы запрашиваемые шаблоном зависят от функции, которую "вызывает этот шаблон"(не корректно наверно сказал, но не суть). Ведь если было бы не так как я сказал, то к чему вообще обращялся бы шаблон?..
Так что есть решение для моей задачи или нету? =)

Добавлено через 1 минуту
П.С. Код какой то левый:
C++
1
"Функция, принимающая T\n"
Т тут является не типом, а буквой, которая стоит в кавычках.
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
22.04.2015, 23:17 #17
Цитата Сообщение от Izual Посмотреть сообщение
Т тут является не типом, а буквой, которая стоит в кавычках.
Это вообще-то к сути явления не относится. Я там мог хоть черта в ступе написать, суть неизменна.
Цитата Сообщение от Izual Посмотреть сообщение
Нет не так, по крайней мере я так думаю.
Нет, это именно так.
Больше добавить нечего.
Цитата Сообщение от Izual Посмотреть сообщение
Ведь если было бы не так как я сказал, то к чему вообще обращялся бы шаблон?..
Он обращается к тому, что ты передал. А передал ты union. Об этом тебе уже писал Nick Alte выше. Какую из функций преобразования вызвать шаблон не знает. В этом проблема.

Добавлено через 19 минут
Цитата Сообщение от Izual Посмотреть сообщение
Так что есть решение для моей задачи или нету? =)
Пока дело не доходит до вызова функции, задачу можно решать средствами языка (хотя конечно не совсем так, как у тебя). Главная сложность заключается в том, что средствами С++ невозможно динамически сформировать прототип для вызова. Прототип в С++ - это единица времени компиляции. Компилятор рассчитывает место на стеке под аргументы, исходя из статической информации о типе. Иными словами, это фундаментальное ограничение, вследствие статической типизации С++ (об этом уже говорилось неоднократно). Без подключения внешних инструментов (ассемблера) решить задачу до конца не получится. Если сузить рамки немного, и попытаться вызывать так не любую функцию, а только такие, которые "понимают" придуманную тобой динамику с юнионами, то задача решается. Но я понимаю, что это тебе не подходит.
0
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,552
23.04.2015, 14:49  [ТС] #18
Цитата Сообщение от DrOffset Посмотреть сообщение
передал ты union
И что с того что передаётся union, из uniona то извлекается то что требует функция. Оно всегда union, но если аргумент указатель, то извлекается 4 байта адреса и по адресу берётся уже значение, если реальное значение то соотв. типу берётся значение из самого uniona.
Я блин и спрашиваю, почему не срабатывает перегруженный оператор, который поидее должен перенаправить получение данных из указателя.
Странные вы.
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
23.04.2015, 16:37 #19
Цитата Сообщение от Izual Посмотреть сообщение
Я блин и спрашиваю, почему не срабатывает перегруженный оператор, который поидее должен перенаправить получение данных из указателя.
А я тебе отвечаю, что он не срабатывает, потому что компилятор не знает к какому типу нужно приводить и не знает, что вообще нужно что-то приводить.
Я тебе пример выше написал. Когда аргумент функции задан типом, а не шаблоном, то оператор срабатывает, когда задан шаблоном, то нет. Потому что шаблон - это не тип. Это потенциально возможное множество типов, потенциально бесконечное. Ну и какой прикажешь вызвать оператор?
Шаблон вывел тип, который передали. Передали ему d (вот здесь)
Цитата Сообщение от Izual Посмотреть сообщение
C++
1
call(v[0][4].d.vp, v[1][2].d, v[1][3].d);
Какого типа у нас d? Правильно, анонимный union. Вот именно этот тип шаблон и вывел.
Еще раз, операторы преобразования работают только если стоит конкретный тип
C++
1
int a = v[1][2].d; // будет вызвано преобразование к int
, тогда компилятор может вычислить, какой из операторов вызвать (смотри еще раз пример с функциями выше). Если там стоит шаблон, то преобразования не будет, будет подстановка фактического аргумента. Если ты передаешь юнион, то юнион и будет параметром шаблона.
Чтобы заработал оператор приведения, нужно подсказать компилятору, какое преобразование необходимо выполнить (например):
C++
1
call(v[0][4].d.vp, (void*)v[1][2].d, (char*)v[1][3].d);
0
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,552
23.04.2015, 16:51  [ТС] #20
Цитата Сообщение от DrOffset Посмотреть сообщение
что шаблон - это не тип
Но ведь третьим аргументом, он же указатель на char понимает. С чего он его понимает, если написан точно так же анонимный юнион?..
Цитата Сообщение от DrOffset Посмотреть сообщение
подсказать компилятору, какое преобразование необходимо выполнить
Вот этот статический метод совсем не катит, я для того и создал такой вот union и шаблон чтоб избавиться от того, чтоб для каждой функции делать привидения статичными. ( и по сути, если бы не эти 8 байт, то можно было бы пользоваться )
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
23.04.2015, 18:06 #21
Цитата Сообщение от Izual Посмотреть сообщение
Вот этот статический метод совсем не катит
Да я понимаю, что не катит. Это демонстрация того почему не работает и что сделать, чтобы "работало".

Цитата Сообщение от Izual Посмотреть сообщение
Но ведь третьим аргументом, он же указатель на char понимает. С чего он его понимает, если написан точно так же анонимный юнион?..
Как ты определил, что он именно "понимает"? Покажи код, о котором ты говоришь, чтобы был предметный разговор.

Знаешь, чтобы прояснить ситуацию, тебе надо задать другие вопросы. Например, тебе наверняка было бы полезно узнать как посмотреть какие именно типы попали в шаблон, чтобы разбираться по факту увиденного. а не по факту догадок. Интересно?
0
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,552
23.04.2015, 18:26  [ТС] #22
Цитата Сообщение от DrOffset Посмотреть сообщение
Как ты определил, что он именно "понимает"? Покажи код, о котором ты говоришь, чтобы был предметный разговор.
Второй пример кода (какой там, 5 чтоли пост), где есть реальный double. Там работает функция atod, и аргументом так же посылается *char.

Цитата Сообщение от DrOffset Посмотреть сообщение
наверняка было бы полезно узнать как посмотреть какие именно типы попали в шаблон
Ага, и поэтому в первой теме в ПС было написанно это:
Цитата Сообщение от Izual Посмотреть сообщение
И ещё, смежный вопрос, как в самом шаблоне проверить какой тип требуется и адрес.
Т.е. хотелось бы чтоб в шаблоне можно было тоже следить за поведением переменных.
Цитата Сообщение от DrOffset Посмотреть сообщение
Интересно?
Очень! =)
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
23.04.2015, 19:48 #23
Цитата Сообщение от Izual Посмотреть сообщение
Ага, и поэтому в первой теме в ПС было написанно это:
Эту формулировку можно воспринять по-разному. Она не столь однозначна, как тебе кажется. Ну да ладно, это не важно.
Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template <typename T>
void print_t()
{
    printf("\n%s\n", __FUNCSIG__);
}
 
template <typename Result, typename... Args>
void call(void * fun, Result& r, Args ... args)
{
    print_t<decltype(call<Result, Args...>)>();
 
    using func_type = Result(_cdecl *)(Args...); // прототип функции
 
    print_t<func_type>();
 
    r = ((func_type)fun) (args...); // вызов функции
}
Строка, которую будет выводить функция print_t, будет содержать в том числе и типы параметров, которые попали в шаблон. Для твоего примера, например, будут такие строки
Это параметры самой функции call (выделил жирным куда смотреть)
void __cdecl print_t<void(void *,union var::<unnamed-type-d> &,union var::<unnamed-type-d>)>(void)
А это прототипа, к которому функция call приводит свой первый параметр:
void __cdecl print_t<unionvar::<unnamed-type-d>(__cdecl *)(union var::<unnamed-type-d>)>(void)
Как видно, получившаяся функция возвращает анонимный юнион и принимает такой же юнион в качестве параметра. Что в точности соответствует тому, что мы писали тебе ранее.

Цитата Сообщение от Izual Посмотреть сообщение
Там работает функция atod, и аргументом так же посылается *char.
Повезло. Бинарно указатель и твой юнион совместимы, поэтому сработало. Если же необходимо из указателя получить значение для передачи в функцию (твой первый вопрос), то совпадением по памяти уже не отделаешься.

Причем твой второй якобы работающий пример, все равно не работает, т.к. возвращает мусор, вместо 123.32. А все потому, что результат функции atof - double. Ты знаешь как возвращаются числа double в ассемблере?
Если проще будет понять на примере, то вот код.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
union test
{
    void * p;
    double d;
};
 
extern "C" double foo1();
extern "C" double foo2();
 
int main()
{
    double f1 = foo1();
    double f2 = foo2();
 
    printf("%lf %lf", f1, f2); //результаты отличаются!
}
Есть две функции, foo1() возвращает в результате обычный double. foo2() эмулирует то, что происходит у тебя.
Реализация функций такая:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
double f = 3.14;
// Функция возвращает double и компилятор знает об этом
extern "C" double foo1()
{
    return f;
}
 
extern "C" double foo2()
{
    // Насильно приведенная функция, теперь компилятор думает, что функция возвращает union test
    test (*fp)() = (test(*)())foo1;
    return fp().d;
}
Итак, результат первой функция напечатает 3.14. Вторая напечатает ноль или что-то невразумительное, не суть. Почему? Потому что ты ввел компилятор в заблуждение. Т.к. double и некий блок памяти 8 байт (наш юнион) возвращаются разными способами.
Для первой функции код, сгенерированный компилятором будет таким
Assembler
1
2
3
_foo1:
    fld QWORD PTR _f
    ret
И это правильный код. Компилятор знает, что функция возвращает double и генерирует оптимальный код для этого. Возвращается значение через стек FPU.
Для второй функции код такой:
Assembler
1
2
3
4
5
6
7
8
_foo2:
    sub esp, 12
    call    _foo1
    mov DWORD PTR [esp], eax
    mov DWORD PTR [esp+4], edx
    fld QWORD PTR [esp]
    add esp, 12
    ret
Сначала вызывается foo1. Пытаемся получить ее результат... во дела, да? Положили-то мы значение в стек FPU, а достаем откуда? Из пары EAX:EDX. Почему так произошло? Потому что компилятор ориентируется на типизацию, когда генерирует код. Объект 8 байт можно и нужно передать через регистры EAX:EDX, а вот double лучше передавать через FPU. Мы обманули его и получили некорректную программу. Если заменить вот этот блок
Assembler
1
2
3
    mov DWORD PTR [esp], eax
    mov DWORD PTR [esp+4], edx
    fld QWORD PTR [esp]
На
Assembler
1
2
    fstp  QWORD PTR [esp]
    fld  QWORD PTR [esp]
То все придет в норму. И числа показываться будут одинаковые.
В твоем коде картина та же.
0
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,552
23.04.2015, 22:27  [ТС] #24
Цитата Сообщение от DrOffset Посмотреть сообщение
Повезло. Бинарно указатель и твой юнион совместимы, поэтому сработало. Если же необходимо из указателя получить значение для передачи в функцию (твой первый вопрос), то совпадением по памяти уже не отделаешься.
оО "совпадение по памяти" это как будто "иголка в стоге сена", адрес в 4 байтах, начиная с v[1][3].d, само значение фиг знает где...
Цитата Сообщение от DrOffset Посмотреть сообщение
все равно не работает, т.к. возвращает мусор
Да точно, хмм, странно, что то видимо я не посмотрел на это, увидел, вроде число и забил))

Откуда все эти ASM вообще ты берёш?.. и чё за FPU))

Добавлено через 10 минут
*Я так понимаю ты меня склоняеш к тому что ассемблерные вставки мне помогут... Ну пойду читать)
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
23.04.2015, 23:22 #25
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Izual Посмотреть сообщение
адрес в 4 байтах, начиная с v[1][3].d, само значение фиг знает где...
Юнион так устроен, что соответствует наиболее вместительному своему полю по размеру, адреса всех полей равны и равны адресу самой переменной юниона. Поэтому, если способ передачи параметра не различается (например как он различается в примере с double), то все равно какой был тип, главное, чтобы в первых его 4х байтах лежало то значение, которое ждет функция (в данном случае значение указателя). Проблемы начались бы, если бы у тебя был еще четвертый параметр, тогда в него попали бы остальные 4 байта твоего юниона (помним, что твой юнион 8 байт из-за double), а настоящий параметр затерялся. Я бы мог это продемонстрировать на примере кода, но все эти посты требуют большого количества времени, которого у меня нет. Если ты уделишь достаточное внимание обучению, то вскоре сам сможешь это делать без моей помощи.

Цитата Сообщение от Izual Посмотреть сообщение
Откуда все эти ASM вообще ты берёш?.. и чё за FPU))
Это дизассемблер примера на С++. Пример в том же посте.
FPU

Цитата Сообщение от Izual Посмотреть сообщение
Я так понимаю ты меня склоняеш к тому что ассемблерные вставки мне помогут... Ну пойду читать)
Я тебя склоняю к тому, что твою задачу можно решать, только если хорошо представлять что происходит на уровне инструкций процессора. В одном из прошлых постов я тебе давал ссылку на библиотеку, где с помощью ассемблера добились того, что ты хочешь. Я утверждаю, что тебе либо придется повторить их путь, либо бросить эту затею.
1
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,552
23.04.2015, 23:31  [ТС] #26
Цитата Сообщение от DrOffset Посмотреть сообщение
где с помощью ассемблера добились того, что ты хочешь. Я утверждаю, что тебе либо придется повторить их путь, либо бросить эту затею.
Ну значит будем штрудировать. =)
Жалко конешно что "просто из перегруженного оператора" нельзя сделать то что я хочу, ну значит есть куда стремиться ещё. Гора, Магомет уже идёт)))
0
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,552
26.04.2015, 16:43  [ТС] #27
DrOffset, да дизассембл интересная вещь... Жаль что твой пример, по крайней мере мне, сложно понять...
C++
1
2
test (*fp)() = (test(*)())foo1;
    return fp().d;
Это какой то лес =)

Собственно пока я тут копаюсь, накопалось оказывается, что без указания типа оператор double не срабатывает вообще. Т.е. на сколько я понял:
С таким подходом:
C++
1
call(v[0][4].d.vp, v[1][2].d, v[1][3].d);
Получается:
Assembler
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
0101B0BC  mov         eax,4  
0101B0C1  shl         eax,0  
0101B0C4  mov         ecx,10h  
0101B0C9  imul        edx,ecx,3  
0101B0CC  mov         ecx,dword ptr ds:[1021324h]  
0101B0D2  mov         eax,dword ptr [ecx+eax]  
0101B0D5  mov         ecx,dword ptr [eax+edx+0Ch]  
0101B0D9  push        ecx  
0101B0DA  mov         edx,dword ptr [eax+edx+8]  
0101B0DE  push        edx  
0101B0DF  mov         eax,4  
0101B0E4  shl         eax,0  
0101B0E7  mov         ecx,10h  
0101B0EC  shl         ecx,1  
0101B0EE  mov         edx,dword ptr ds:[1021324h]  
0101B0F4  mov         eax,dword ptr [edx+eax]  
0101B0F7  lea         ecx,[eax+ecx+8]  
0101B0FB  push        ecx  
0101B0FC  mov         edx,4  
0101B101  imul        eax,edx,0  
0101B104  mov         ecx,10h  
0101B109  shl         ecx,2  
0101B10C  mov         edx,dword ptr ds:[1021324h]  
0101B112  mov         eax,dword ptr [edx+eax]  
0101B115  mov         ecx,dword ptr [eax+ecx+8]  
0101B119  push        ecx  
0101B11A  call        call<var::<unnamed-type-d>,var::<unnamed-type-d> > (0101150Ah)  
0101B11F  add         esp,10h
А с таким:
C++
1
call(v[0][4].d.vp, (double)v[1][2].d, v[1][3].d);
Вот что:
Assembler
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
01145B7C  mov         eax,4  
01145B81  shl         eax,0  
01145B84  mov         ecx,10h  
01145B89  imul        edx,ecx,3  
01145B8C  mov         ecx,dword ptr ds:[1151324h]  
01145B92  mov         eax,dword ptr [ecx+eax]  
01145B95  mov         ecx,dword ptr [eax+edx+0Ch]  
01145B99  push        ecx  
01145B9A  mov         edx,dword ptr [eax+edx+8]  
01145B9E  push        edx  
01145B9F  mov         eax,4  
01145BA4  shl         eax,0  
01145BA7  mov         ecx,10h  
01145BAC  shl         ecx,1  
01145BAE  mov         edx,dword ptr ds:[1151324h]  
01145BB4  mov         eax,dword ptr [edx+eax]  
01145BB7  lea         ecx,[eax+ecx+8]  
01145BBB  call        var::<unnamed-type-d>::operator double & (0114150Fh)  
01145BC0  push        eax  
01145BC1  mov         ecx,4  
01145BC6  imul        edx,ecx,0  
01145BC9  mov         eax,10h  
01145BCE  shl         eax,2  
01145BD1  mov         ecx,dword ptr ds:[1151324h]  
01145BD7  mov         edx,dword ptr [ecx+edx]  
01145BDA  mov         eax,dword ptr [edx+eax+8]  
01145BDE  push        eax  
01145BDF  call        call<double,var::<unnamed-type-d> > (01141514h)  
01145BE4  add         esp,10h
Хотя почему они все dword я ещё не вкурил...

Добавлено через 13 минут
Ну и естественно из за этого сам шаблон уже по другому вопринимает данные. Без типа:
Assembler
1
2
3
4
5
6
7
8
00942FC0  call        __RTC_CheckEsp (0941370h)  
00942FC5  mov         dword ptr [ebp-0CCh],eax  
00942FCB  mov         dword ptr [ebp-0C8h],edx  
00942FD1  mov         edx,dword ptr [r]  
00942FD4  mov         eax,dword ptr [ebp-0CCh]  
00942FDA  mov         dword ptr [edx],eax  
00942FDC  mov         ecx,dword ptr [ebp-0C8h]  
00942FE2  mov         dword ptr [edx+4],ecx
С типом:
Assembler
1
2
3
00FF2FC0  call        __RTC_CheckEsp (0FF1370h)  
00FF2FC5  mov         edx,dword ptr [r]  
00FF2FC8  fstp        qword ptr [edx]
Как ты и сказал, похожая ситуация.

Добавлено через 7 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
либо придется повторить их путь, либо бросить эту затею
Может есть обходной кстати вариант. Например меня одолевает мысль, что т.к. в принципе я имею в структуре уже известный тип, то можно было бы приводить аргументы в шаблоне. (static_cast'ом чтоль, это хоть и по коду займёт место, но зато это предполагаю будет эмулировать поведения для опр. типа, и тут уже я смогу и колдовать сразу с указателями, как в общем то я и хотел сделать с double)

Добавлено через 17 часов 12 минут
Цитата Сообщение от Nick Alte Посмотреть сообщение
Функция call. Она получает указатель на функцию, у которого выдрана вся информация об аргументах и возвращаемом значении.
Оказалось что прототип функции в шаблоне действительно себя странно ведёт.
C++
1
using func_type = Result(_cdecl *)(Args...); // прототип функции
Заменив Result (т.е. тип union) на double получил в дизассембле qword...
Лан, ушёл дальше ковыряться)
0
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,552
28.04.2015, 21:39  [ТС] #28
Перегруженный оператор uniona не дал в итоге мне возможность возвращять разные типы значений.

Может ли функция вернуть разный тип? Читал про перегрузку функций и шаблоны, но ни то ни другое пока не нашёл как применить в виду следующих причин:
1. Перегруженная функция обязана иметь разные типы или кол-во аргументов. А у меня аргумент всегда один (структура).
2. Шаблонная функция требует статически написать тип, например:
C++
1
user_function<int>(3);
Либо иметь статический тип возвращяемого параметра, например:
C++
1
int a = user_f(3);
У меня же из функции должен выйти тип, соотв. например числу.
Подразумевается:
C++
1
2
3
4
5
6
7
8
9
10
11
template <typename T1>
T GetVar(var v)
{
    int type = v.t;
    bool b = v.d.b;
    int i = v.d.i;
    if(type == 0)
        return b;
    else
        return i;
}
Только тут будет нужно опять же написать в угловых скобках тип, а мне надо без этого.

Использовать хочу для вызова своей функции:
C++
1
call(v[0][4].d.vp, GetVar(v[1][2]), GetVar(v[1][3]));
Где call ->
C++
1
2
3
template<typename Result, typename... Args>
void call(void * fun, Result& r, Args ... args)
...
0
gray_fox
What a waste!
1521 / 1226 / 70
Регистрация: 21.04.2012
Сообщений: 2,565
Завершенные тесты: 3
28.04.2015, 22:27 #29
Цитата Сообщение от Izual Посмотреть сообщение
У меня же из функции должен выйти тип, соотв. например числу.
Если "соответствие числу" определяется на этапе исполнения программы, то шаблоны и перегрузка не помогут, т.к. это статический полиморфизм, т.е. здесь например
Цитата Сообщение от Izual Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
template <typename T1>
T GetVar(var v)
{
* * int type = v.t;
* * bool b = v.d.b;
* * int i = v.d.i;
* * if(type == 0)
* * * * return b;
* * else
* * * * return i;
}
тип T должен быть определён до исполнения программы.
0
Izual
94 / 119 / 6
Регистрация: 13.11.2012
Сообщений: 1,552
28.04.2015, 22:34  [ТС] #30
Цитата Сообщение от gray_fox Посмотреть сообщение
Если "соответствие числу" определяется на этапе исполнения программы
Надо в runtime...

Добавлено через 1 минуту
Цитата Сообщение от gray_fox Посмотреть сообщение
шаблоны и перегрузка не помогут
А что может помочь? (я конешно уже получил вариант с dyncall от offseta, но сторонняя библиотека..)
0
28.04.2015, 22:34
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.04.2015, 22:34
Привет! Вот еще темы с ответами:

Ошибка при перегрузке оператора >> - C++
Приветствую. Есть 2 класса: enum Color { white = 1, red, green, blue, yellow }; class Shape { protected: Color figureCol; ...

Предупреждение при перегрузке оператора - C++
Есть вот такой код для созданный для обучения #include &lt;iostream&gt; using namespace std; class complex{ private: ...

Ошибка при перегрузке оператора + - C++
Имеется класс, который представляет из себя строку и количество символов в ней. Задача - перегрузить оператор +, чтобы он складывал нам две...

Variadic template lambda capture - C++
Доброго всем дня! Речь пойдёт об C++14, в котором стало возможным делать прямую передачу в замыкание: auto my_lambda = () { /*...


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru