143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
1

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

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

Author24 — интернет-сервис помощи студентам
Есть вот такой вот код (сделан в 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)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.04.2015, 16:19
Ответы с готовыми решениями:

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

Ошибка при перегрузке оператора ==
У меня компилятор выдает ошибку error LNK2019: ссылка на неразрешенный внешний символ &quot;bool __cdecl...

Ошибка при перегрузке оператора <<
class Predmet { private: int id; string name; public: Predmet() {}; Predmet(string name,...

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

35
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
20.04.2015, 13:31  [ТС] 2
Ну так шо, нету никаких соображений?..
0
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
20.04.2015, 18:56 3
Очень уж запутанный и непонятный вопрос. Выражения вроде "хочу, чтобы нужная переменная вызывалась из указателя" и "шаблон ссылается на адрес" тоже ясности не добавляют. А уж без понимания замысла, стоящего за этим нагромождением объединений и однобуквенных имён, разобраться совсем трудно. Ну и тексты сообщений об ошибке не повредили бы делу.
0
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
20.04.2015, 20:16  [ТС] 4
Цитата Сообщение от Nick Alte Посмотреть сообщение
хочу, чтобы нужная переменная вызывалась из указателя
В общем то это и хочу. Почему: хочу уменьшить размер uniona до 4 байт, для этого надо избавиться от 8 байтовых типов, как - либо их не использовать совсем (что невозможно просто, т.к. они нужны), либо использовать указатель на них, т.к. указатель 4 байтный, то это бы решило проблему, но не работает...

Цитата Сообщение от Nick Alte Посмотреть сообщение
тексты сообщений об ошибке
Line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
52 строка это:
Цитата Сообщение от Izual Посмотреть сообщение
return pd[0];
Уже как тока не пробовал... Никак... совсем. (и вообще мне кажется шаблон даже не обращяет внимание на перегруженный оператор, а ссылается именно к адресу переменной, т.е. к адресу v[1][2].d, но никак не к указателю на pd[0])
*Прикрепил принт ошибки.
И да, ошибка возникает при удалении "delete[] v[1][2].d.pd;" (потому что до "cout << "End Programm" << endl;" не доходит)
Миниатюры
Перенаправление указателя при перегрузке оператора в variadic template  
0
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
20.04.2015, 22:21 5
Ошибка возникает из-за путаницы с выделением-освобождением (вероятно, какой-то участок памяти удаляется повторно).
0
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
20.04.2015, 22:31  [ТС] 6
Цитата Сообщение от Nick Alte Посмотреть сообщение
из-за путаницы с выделением-освобождением
НЕТ с выделением памяти и удалением всё ок.
Результат функции видели на картинке? Она выдаёт не верный ответ, а должен быть как в тестовом примере. Я предполагаю(УВЕРЕН!), что: при направлении v[1][2].d аргумента в шаблоне заполняется не pd элемент, а 8 байт начиная с "&v[1][2].d", т.е. не в указатель на pd[0], а сам .d адрес, в итоге затирается pd указатель на выделенный массив, и результат - невозможно удалить указатель, т.к. адрес к нему был затёрт результатом функции.
П.С. Я 100% нуб, и то понимаю это)))
0
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
21.04.2015, 18:54 7
Ну тогда попробуем выяснить, вокруг чего такой кипеш. Функция call. Она получает указатель на функцию, у которого выдрана вся информация об аргументах и возвращаемом значении. Она получает пару экземпляров union, один из которых используется для получения результата, а другой передаётся в вызываемую функцию. Предполагается, что функция вернёт тот же union, который записывается в r. Однако же atof возвращает double, а не означенный union. Отсюда и проблемы. Половина возвращённого double впихивается в union и позже интерпретируется как указатель, а половина попросту теряется.
0
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
21.04.2015, 20:02  [ТС] 8
Цитата Сообщение от Nick Alte Посмотреть сообщение
функция вернёт тот же union, который записывается в r
ЧТо, куда? Указатель на функцию - это первый аргумент с типом PVOID. Второй аргумент - возвратное значение, тип POINTER DOUBLE. Третий параметр - аргумент самой функции "atof".
Цитата Сообщение от Izual Посмотреть сообщение
call(v[0][4].d.vp, v[1][2].d, v[1][3].d);
Тетстовый и работающий пример в коде:
Цитата Сообщение от Izual Посмотреть сообщение
v[1][2].d.pd[0] = atof(v[1][3].d.pc);
Цитата Сообщение от Nick Alte Посмотреть сообщение
atof возвращает double, а не означенный union
Atof возвращяет double, именно реальный, а не указатель, если бы он вернул указатель, то всё было бы ок.
О чём ты говориш я вообще не вдупляю. Пустословием не занимайся, явно покажи как исправить.
До этого я тестировал с такими поправками:
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
#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;
        double d; // поправка 1
        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 d; // поправка 2
        }
        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.d = NULL; // поправка 3
    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");
    /* поправка 4
    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.d = atof(v[1][3].d.pc); // поправка 5 (чисто для теста)
    cout << "Test atof result: " << v[1][2].d.d << endl; // тут тоже поправка в выводе
    v[1][2].d.d = NULL; // и тут в обнулении после теста
    //
    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;
            Cur = 0;
            call(v[0][4].d.vp, v[1][2].d, v[1][3].d); // поправка 6
            if (v[1][2].d.d == NULL)
                cout << "Failed result, error: " << endl;
            else
            {
                cout << "Returned DOUBLE: " << v[1][2].d.d << endl; // поправка 7
            }
        }
        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; поправка 8
    delete[]v[1];
    delete[]v;
    return res;
}
И в данном случае всё работает. Но это не вариант, я хочу уменьшить размер uniona. Сделать это можно только если вместо реальной переменной типа double будет указатель на него.
0
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
21.04.2015, 20:24 9
То, что ты не понимаешь, о чём я говорю, не значит, что я занимаюсь пустословием. Это значит, что тебе надо восполнять пробелы в знаниях, а также внимательно перечитывать непонятные места.
Так уж и быть, объясню повторно, специально для сумрачных гениев. Функция atof возвращает 8-байтовый double, согласно cdecl calling convention, это значение возвращается в регистрах EAX и EDX. В функции call написано:
C++
1
r = ((func_type)fun) (args...);
, причём про fun компилятор думает, что он возвращает твой union, занимающий 4 байта, а r в нашем случае - ссылка на v[1][2].d. То есть, половина вернувшегося числа, содержавшаяся в EAX, попадает в сыром виде внутрь v[1][2].d. Другая половина данных игнорируется. После того, как эти полчисла туда занесены, ты обращаешься с этой переменной как с указателем на double, каковым её содержимое категорически не является, и получаешь закономерный результат.
Как исправить - тут уж сам страдай, я в эту невменяемую кашу со стиранием типов лезть не хочу.
1
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
21.04.2015, 21:13  [ТС] 10
Цитата Сообщение от Nick Alte Посмотреть сообщение
про fun компилятор думает, что он возвращает твой union, занимающий 4 байта
Причём тут fun ? Это лишь указатель на функцию, не более. И он не имеет отношения к размеру double аргумента. Более того, я повторно показал код, который демонстрирует что с реальным double всё работает.
Цитата Сообщение от Nick Alte Посмотреть сообщение
для сумрачных гениев
Желчь можете оставить себе.
0
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
21.04.2015, 21:38 11
Цитата Сообщение от Izual Посмотреть сообщение
Причём тут fun ? Это лишь указатель на функцию, не более.
При том, что при инстанциации шаблона call этому указателю явно вменяется определённый тип. В этом типе, помимо прочего, указано, что эта функция возвращает Result (то есть, тот самый многострадальный 4-байтный union). И когда в fun передаётся адрес atof (возвращающий результат в EAX:EDX), внутри данной инстанциации call всё равно генерируется вызов, соответствующий вменённому типу, игнорирующий содержимое EDX и заносящий содержимое EAX в v[1][2].d по ссылке. Ну и понятное дело, что при прямом вызове atof в твоём "примере, в котором всё работает" всё шоколадно: там-то в месте вызова имеется полная информация как об аргументе, так и о возвращаемом значении. А вот внутри call о переданной туда функции уже абсолютно ничего неизвестно, и приходится руководствоваться тем, что ты сообщишь. То есть, типом, к которому приводится fun, не имеющим ничего общего с atof кроме количества аргументов.
0
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
22.04.2015, 05:38  [ТС] 12
Цитата Сообщение от Nick Alte Посмотреть сообщение
типом, к которому приводится fun, не имеющим ничего общего с atof кроме количества аргументов
Так 8 байт же должно передаться, для этого и перегруженный оператор должен перенаправить результат в указатель, в котором есть место для этих 8 байт. Ведь если в функции явно аргумент или возвращяемое значение типа поинтера, то тоже всё шоколадно.
Цитата Сообщение от Nick Alte Посмотреть сообщение
полная информация как об аргументе, так и о возвращаемом значении
а для чего это шаблону? это запрашивает сама функция из списка аргументов в шаблоне, там уж что дадут то и будет, я потому и хочу подменить адрес с v[1][2].d на указатель... чтоб туда адрес значение писал.(в данном случае)

Добавлено через 4 минуты
C++
1
call(v[0][4].d.vp, v[1][2].d, v[1][3].d); // поправка 6
Точно так же неявно передаётся, и никакой информации не несёт. (.d тут это union, явным было бы v[1][2].d.d)
0
Эксперт С++
1674 / 1046 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
22.04.2015, 19:03 13
С какой бы стороны зайти, чтобы пробиться сквозь эту стену упрямого непонимания...
Вот все эти операторы преобразования - они работают тогда, когда есть несоответствие реального и ожидаемого типа.
В функции call такого несоответствия нет, там всё идеально совпадает. Потому что там из типов данных - только этот невменяемый union. Потому что именно он передаётся в call при вызове. union передаётся в call, union передаётся дальше в вызываемую функцию, возвращаемое ей значение интерпретируется как union и тупо побайтово копируется в r.
0
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
22.04.2015, 19:36  [ТС] 14
Цитата Сообщение от Nick Alte Посмотреть сообщение
С какой бы стороны зайти
Цитата Сообщение от Nick Alte Посмотреть сообщение
невменяемый union.
Чё ты прицепился к этому union'у? Меня интересует почему перегруженный оператор не срабатывает, и не перенаправляет double в pd[0]. ~ ~
0
18822 / 9826 / 2401
Регистрация: 30.01.2014
Сообщений: 17,260
22.04.2015, 21:43 15
Цитата Сообщение от Izual Посмотреть сообщение
Меня интересует почему перегруженный оператор не срабатывает, и не перенаправляет double в pd[0].
Он тебе на это и ответил. Для того, чтобы сработал оператор, нужно, чтобы, грубо говоря, в левой части выражения был требуемый тип. А там у тебя шаблон.
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
#include <cstdio>
 
struct Test
{
    operator int()
    {
        printf("Вызов оператора преобразования к int\n");
        return value; 
    }
    
    int value;
};
 
 
void test1(int x)
{
    printf("Функция, принимающая int\n");
}
 
template <typename T>
void test2(T x)
{
    printf("Функция, принимающая T\n");
}
 
int main()
{
    Test v = { 10 };
    
    test1(v); // здесь известен тип, к которому нужно преобразовать
    
    printf("-----------------------------\n");
    
    test2(v); // а здесь нет, поэтому шаблон подставит тот тип, который передали, т.е. Test     
}
Смотри поведение в рантайме здесь.
0
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
22.04.2015, 22:36  [ТС] 16
Цитата Сообщение от DrOffset Посмотреть сообщение
в левой части выражения был требуемый тип. А там у тебя шаблон.
Нет не так, по крайней мере я так думаю. Одно дело у тебя какой то там пустой шаблон, а другое дело когда аргументы запрашиваемые шаблоном зависят от функции, которую "вызывает этот шаблон"(не корректно наверно сказал, но не суть). Ведь если было бы не так как я сказал, то к чему вообще обращялся бы шаблон?..
Так что есть решение для моей задачи или нету? =)

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

Добавлено через 19 минут
Цитата Сообщение от Izual Посмотреть сообщение
Так что есть решение для моей задачи или нету? =)
Пока дело не доходит до вызова функции, задачу можно решать средствами языка (хотя конечно не совсем так, как у тебя). Главная сложность заключается в том, что средствами С++ невозможно динамически сформировать прототип для вызова. Прототип в С++ - это единица времени компиляции. Компилятор рассчитывает место на стеке под аргументы, исходя из статической информации о типе. Иными словами, это фундаментальное ограничение, вследствие статической типизации С++ (об этом уже говорилось неоднократно). Без подключения внешних инструментов (ассемблера) решить задачу до конца не получится. Если сузить рамки немного, и попытаться вызывать так не любую функцию, а только такие, которые "понимают" придуманную тобой динамику с юнионами, то задача решается. Но я понимаю, что это тебе не подходит.
0
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
23.04.2015, 14:49  [ТС] 18
Цитата Сообщение от DrOffset Посмотреть сообщение
передал ты union
И что с того что передаётся union, из uniona то извлекается то что требует функция. Оно всегда union, но если аргумент указатель, то извлекается 4 байта адреса и по адресу берётся уже значение, если реальное значение то соотв. типу берётся значение из самого uniona.
Я блин и спрашиваю, почему не срабатывает перегруженный оператор, который поидее должен перенаправить получение данных из указателя.
Странные вы.
0
18822 / 9826 / 2401
Регистрация: 30.01.2014
Сообщений: 17,260
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
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
23.04.2015, 16:51  [ТС] 20
Цитата Сообщение от DrOffset Посмотреть сообщение
что шаблон - это не тип
Но ведь третьим аргументом, он же указатель на char понимает. С чего он его понимает, если написан точно так же анонимный юнион?..
Цитата Сообщение от DrOffset Посмотреть сообщение
подсказать компилятору, какое преобразование необходимо выполнить
Вот этот статический метод совсем не катит, я для того и создал такой вот union и шаблон чтоб избавиться от того, чтоб для каждой функции делать привидения статичными. ( и по сути, если бы не эти 8 байт, то можно было бы пользоваться )
0
23.04.2015, 16:51
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.04.2015, 16:51
Помогаю со студенческими работами здесь

Ошибки при перегрузке оператора <<
dc.cpp не видит private поля из dc.h dc.h #pragma once #include &lt;cmath&gt; class dc {

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

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

Variadic template
Добрый день, господа. Будьте добры, помогите кто может. Есть у меня шаблонный класс ...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru