Помогите с выведением и преобразованием типа
От: Alexander Pazdnikov  
Дата: 22.12.09 12:57
Оценка:
Здравствуйте, Коллеги.

Задача передать в функцию массив: указатель на первый член и размер

Чтобы не генерить разные тела шаблонной функции для разных статических массивов, сделал шаблонную функцию make_carray в которой вычисляется размер массива и возвращается объектик массива.
Помогите, пожалуйста, упростить и убрать вложенный вызов make_carray

#include <iostream>

using namespace std;

/* обертка для массива */
template<typename T>
struct carray
{
    T *parr;
    size_t size;
};

/* вспомогательная функция для вычисления размера массива */
template<typename T, size_t N> 
carray<T> make_carray(T (&arr)[N])
{
    carray<T> res = {arr, N};
    return res;
}

/* сама полезная работа */
void f1(const carray<int>& arr)
{
    for (size_t i = 0; i < arr.size; ++i)
    {
        cout << arr.parr[i] << endl;
    }
}

int main(int argc, char *argv[])
{
    int data[] = {1, 2, 3};
    
    f1(make_carray(data)); // вложенный вызов make_carray, от которого хочется избавиться
    
    return 0;
}


хочется чтобы работало без make_carray
int main(int argc, char *argv[])
{
    int data[] = {1, 2, 3};
    
    [b]f1(data); // избавились от вложенного вызова make_carray
    
    return 0;
}
array
Re: Помогите с выведением и преобразованием типа
От: jazzer Россия Skype: enerjazzer
Дата: 22.12.09 14:46
Оценка: +2
Здравствуйте, Alexander Pazdnikov, Вы писали:

AP>Помогите, пожалуйста, упростить и убрать вложенный вызов make_carray

AP>хочется чтобы работало без make_carray

добавление конструктора в carray поможет?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Помогите с выведением и преобразованием типа
От: ArtDenis Россия  
Дата: 22.12.09 16:15
Оценка:
Оффтоп: а почему тема так называется?
... << RSDN@Home 1.2.0 alpha 4 rev. 1324>>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: Помогите с выведением и преобразованием типа
От: Bell Россия  
Дата: 23.12.09 02:55
Оценка: 2 (1)
Здравствуйте, Alexander Pazdnikov, Вы писали:

Добавь перегрузку для своей функции
#include <iostream>

using namespace std;

/* обертка для массива */
template<typename T>
struct carray
{
    T *parr;
    size_t size;
};

/* сама полезная работа */
void f1(const carray<int>& arr)
{
    for (size_t i = 0; i < arr.size; ++i)
    {
        cout << arr.parr[i] << endl;
    }
}

template<typename T, size_t N> 
void f1(T (&arr)[N])
{
   carray<T> res = {arr, N};
   f1(res);
}

int main(int argc, char *argv[])
{
    int data[] = {1, 2, 3};
    
    f1(data);
    
    return 0;
}


Да, и обертка carray мне кажется соверженно ненужной — можно в f1 сразу передавать указатель и размер
Любите книгу — источник знаний (с) М.Горький
Re[2]: Помогите с выведением и преобразованием типа
От: Alexander Pazdnikov  
Дата: 23.12.09 07:23
Оценка:
Здравствуйте, Bell, Вы писали:

За подсказку с перегрузкой — спасибо.

B>Да, и обертка carray мне кажется соверженно ненужной — можно в f1 сразу передавать указатель и размер


Сама функция довольно большая, хотелось предотвратить инстанцирование шаблонной функции для каждого отдельного массива.

template <size_t N>
void f1(int (&data)[N])
{
     for (int i = 0; i < N; ++i)
     {
         cout << data[i] << endl;
     }
}

int some_func()
{
    int d1[] = {1, 2, 3};
    f1(d1);

    int d2[] = {3, 2, 1};
    f1(d1);
}


Сгенерятся две копии одной функции, а функция библиотечная, т.е. используется > 20 раз сейчас, и это кол-во будет увеличиваться.

Хотел уточнить — выход, так понимаю, генерить обертки функций

/* Полезная функция */
void f1(int *data, size_t size)
{
     for (size_t i = 0; i < size; ++i)
     {
         cout << data[i] << endl;
     }
}

/* Обертка для полезной функции для вычисления размера массива */
template <size_t N>
void f1(int (&data)[N])
{
    f1(data, N);
}

int some_func()
{
    int d1[] = {1, 2, 3};
    f1(d1);

    int d2[] = {3, 2, 1};
    f1(d1);
}
Re[2]: Помогите с выведением и преобразованием типа
От: Alexander Pazdnikov  
Дата: 23.12.09 07:27
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Оффтоп: а почему тема так называется?


Потому что изначально хотел автоматически преобразовывать int data[10] в carray
Re[3]: Помогите с выведением и преобразованием типа
От: Bell Россия  
Дата: 23.12.09 08:57
Оценка: 3 (1)
Здравствуйте, Alexander Pazdnikov, Вы писали:

AP>Сама функция довольно большая, хотелось предотвратить инстанцирование шаблонной функции для каждого отдельного массива.


AP>
AP>template <size_t N>
AP>void f1(int (&data)[N])
AP>{
AP>     for (int i = 0; i < N; ++i)
AP>     {
AP>         cout << data[i] << endl;
AP>     }
AP>}

AP>int some_func()
AP>{
AP>    int d1[] = {1, 2, 3};
AP>    f1(d1);

AP>    int d2[] = {3, 2, 1};
AP>    f1(d1);
AP>}
AP>


AP>Сгенерятся две копии одной функции...


В данном случае сгенерится одна функция, даже если второй вызов исправить на f1(d2), потому что типы d1 и d2 идентичны. Две функции сгенерятся, если, например, d2 определить так:
int d2[] = {1, 2, 3, 4};


AP>... , а функция библиотечная, т.е. используется > 20 раз сейчас, и это кол-во будет увеличиваться.



AP>Хотел уточнить — выход, так понимаю, генерить обертки функций

Ну да, в спец. перегрузке выводить размер, и потом вызывать "рабочую" функцию. И не стоит беспокоиться о количестве сгенерироанных функций-переходников — оптимизатор вполне способен выкинуть их вовсе.
Вот небольшой пример:

void __declspec(noinline) f(int* ptr, int sz)//Не встраивать, чтобы меньше кода получилось в ассемблерном листинге :)
{
   for(int i = 0; i < sz; ++i)
      cout << ptr[i] << '\n';

   cout << '\n';
}

template <class T, int N>
void f(T (&arr)[N])
{
   f(arr, N);
}

int main()
{
   int a1[] = {5, 6, 7};
   int a2[] = {8, 9, 10, 11};

   f(a1);
   f(a2);
  
   return 0;
}


И вот что сгенерировал VC7.1:

_main    PROC NEAR                    ; COMDAT

; 83   : {

    sub    esp, 28                    ; 0000001cH

; 84   :    int a1[] = {5, 6, 7};
; 85   :    int a2[] = {8, 9, 10, 11};
; 86   : 
; 87   :    f(a1);

    lea    eax, DWORD PTR _a1$[esp+28]
    push    3
    push    eax
    mov    DWORD PTR _a1$[esp+36], 5
    mov    DWORD PTR _a1$[esp+40], 6
    mov    DWORD PTR _a1$[esp+44], 7
    mov    DWORD PTR _a2$[esp+36], 8
    mov    DWORD PTR _a2$[esp+40], 9
    mov    DWORD PTR _a2$[esp+44], 10        ; 0000000aH
    mov    DWORD PTR _a2$[esp+48], 11        ; 0000000bH
    call    ?f@@YAXPAHH@Z                ; f

; 88   :    f(a2);

    lea    ecx, DWORD PTR _a2$[esp+36]
    push    4
    push    ecx
    call    ?f@@YAXPAHH@Z                ; f

Как видишь, никаких переходников и близко не видать — компилятор просто сразу подставил выведенные значения
Любите книгу — источник знаний (с) М.Горький
Re[2]: Помогите с выведением и преобразованием типа
От: Alexander Pazdnikov  
Дата: 23.12.09 09:03
Оценка:
Здравствуйте, jazzer, Вы писали:

J>добавление конструктора в carray поможет?


По-моему, как-то не правилно понял ваш совет по добалению конструктора: приходится указывать размер массива явно ?
Поправьте, пожалуйста.

#include <iostream>

using namespace std;

template<typename T, size_t N>
struct carray
{
    carray(T (&arr)[N]) : parr(arr), size(N) // добавил конструктор
    {
    }
    T *parr;
    size_t size;
};

template <size_t N>
void f1(const carray<int, N>& arr)
{
    for (size_t i = 0; i < arr.size; ++i)
    {
        cout << arr.parr[i] << endl;
    }
}

int main(int argc, char *argv[])
{
    int data[] = {1, 2, 3};
....
//  f1(make_carray(data));
    f1(carray<int, 3>(data)); // приходиться явно указывать размер массива

    f1(data); // так не компилиться, говорит - ошибка: нет соответствующей функции для вызова ‘f1(int [3])
}
Re[3]: Помогите с выведением и преобразованием типа
От: Bell Россия  
Дата: 23.12.09 09:24
Оценка: 2 (1) +1
Здравствуйте, Alexander Pazdnikov, Вы писали:

AP>По-моему, как-то не правилно понял ваш совет по добалению конструктора: приходится указывать размер массива явно ?

AP>Поправьте, пожалуйста.

Я думаю, jazzer имел в виду что-то такое:

template<typename T>
struct carray
{
    template <int N>
    carray(T (&arr)[N]) : parr(arr), size(N) {}

    T *parr;
    size_t size;
};

/* сама полезная работа */
void f1(const carray<int>& arr)
{
    for (size_t i = 0; i < arr.size; ++i)
    {
        cout << arr.parr[i] << endl;
    }
}

int main(int argc, char *argv[])
{
    int data[] = {1, 2, 3};    
    f1(data);
    
    return 0;
}
Любите книгу — источник знаний (с) М.Горький
Re[4]: Помогите с выведением и преобразованием типа
От: Alexander Pazdnikov  
Дата: 23.12.09 10:44
Оценка:
Здравствуйте, Bell, Вы писали:

Число академический интерес, как можно шаблонизировать функцию f1 для вывода типа T элементов массива

template<typename T>
struct carray
{
    template <int N>
    carray(T (&arr)[N]) : parr(arr), size(N) {}

    T *parr;
    size_t size;
};

/* сама полезная работа */
template <typename T>
void f1(const carray<T>& arr) 
{
    for (size_t i = 0; i < arr.size; ++i)
    {
        cout << arr.parr[i] << endl;
    }
}

int main(int argc, char *argv[])
{
    int data[] = {1, 2, 3};    
    f1(data); // ошибка: нет соответствующей функции для вызова ‘f1(int [3])'
    
    return 0;
}
Re[5]: Помогите с выведением и преобразованием типа
От: Bell Россия  
Дата: 23.12.09 12:03
Оценка:
Здравствуйте, Alexander Pazdnikov, Вы писали:

AP>Число академический интерес, как можно шаблонизировать функцию f1 для вывода типа T элементов массива

В данном случае никак — преобразование T[N] -> carray<T> не рассматривается. Нужно либо явно указыватьпараметр шаблона при вызове, либо использовать вариант без carray.
Любите книгу — источник знаний (с) М.Горький
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.