Форум программистов, компьютерный форум CyberForum.ru

Шаблонные функции только для определённых типов! - C++

Восстановить пароль Регистрация
 
popelyuk
 Аватар для popelyuk
8 / 8 / 1
Регистрация: 04.12.2012
Сообщений: 130
20.01.2013, 12:20     Шаблонные функции только для определённых типов! #1
Как сделать чтобы для шаблонной функции генерировались только экземпляры для нескольких заданных типов, а остальные не генерировались?
Следующее определение не помогает (в конце кода):
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
template <typename str_type>
double strToDouble(str_type *in_add, const str_type decimal_separator='.');
 
template <typename str_type>
double strToDouble(str_type *in_add, const str_type decimal_separator) {
    auto_arr<str_type> str=cloneStr(in_add); // for sake able to modify
    str_type *int_pos(str), *fract_pos(0), *exp_pos(0);
    if((*str=='+')||(*str=='-')) str++;
    bool is_hex((str[0]=='0')&&(str[1]=='x'));
    while(*str!=0) {
        if((*str==decimal_separator)&&(fract_pos==0)) *str=0, fract_pos=++str;
        if(((*str=='e')||(*str=='E'))&&(exp_pos==0)) {
            if(is_hex&&((str[1]!='0')||(str[2]!='x'))) continue;
            *str=0; exp_pos=++str; break;
        }
    }
    // check here that the fractional, integer and exponential part not equal zero !!
    double out_number=strToInt(int_pos);
    if(fract_pos) {
        out_number;
    }
    if(exp_pos)
    return out_number;
}
 
template double strToDouble(char *in_add, const char decimal_separator);
template double strToDouble(wchar_t *in_add, const wchar_t decimal_separator);
проблема состоит в том что если вызвать функцию как:
C++
1
std::cout<<"strToDouble="<<strToDouble("k")<<std::endl;
то подставляется const char вместо str_type, а надо просто char, потому что тогда всё что внутри объявлено с типом str_type нельзя изменять что никоим образом мне не подходит! Помогает:
C++
1
std::cout<<"strToDouble="<<strToDouble<char>("k")<<std::endl;
но это не удобно постоянно писать тип при вызове функции, теряется весь смысл "template'ности" ))
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.01.2013, 12:20     Шаблонные функции только для определённых типов!
Посмотрите здесь:

C++ Шаблонные функции
C++ Шаблонные функции
C++ Шаблонные функции
Шаблонные функции C++
Шаблонные классы. Присвоение к указателю и приведение типов C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
20.01.2013, 12:31     Шаблонные функции только для определённых типов! #2
Цитата Сообщение от popelyuk Посмотреть сообщение
о подставляется const char вместо str_type, а надо просто char
"k" - это строковый литерал, его символы костантны, поэтому и выводится const char, а не char. Почему бы просто не объявить in_add как str_type const*?
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
20.01.2013, 12:34     Шаблонные функции только для определённых типов! #3
можно внутри попробовать заюзать удалятор константы.
что-нибубдь типа
typedef typename boost::remove_const<str_type>::type non_const_str_type;
и там, где надо менять переменную использовать non_const_str_type вместо str_type
в новом стандарте такая штука возможно уже в std
popelyuk
 Аватар для popelyuk
8 / 8 / 1
Регистрация: 04.12.2012
Сообщений: 130
20.01.2013, 12:51  [ТС]     Шаблонные функции только для определённых типов! #4
Цитата Сообщение от DU Посмотреть сообщение
можно внутри попробовать заюзать удалятор константы.
что-нибубдь типа
typedef typename boost::remove_const<str_type>::type non_const_str_type;
и там, где надо менять переменную использовать non_const_str_type вместо str_type
в новом стандарте такая штука возможно уже в std
как не смешно, но есть решение проще, только что нашёл, такое смешное я просто в шоке, нужно для этого его объявить const str_type тогда в str_type подставляется только char из-за того, скорее всего, что если бы поставлялось const char, то было бы const const char - что есть ошибка!

Добавлено через 4 минуты
Ну а вообще тема остаётся открытой, как для template функции генерировать только определённые инстанации?? И запрещать генерировать остальные?
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
20.01.2013, 13:44     Шаблонные функции только для определённых типов! #5
Цитата Сообщение от popelyuk Посмотреть сообщение
как для template функции генерировать только определённые инстанации?? И запрещать генерировать остальные?
Объявить эту функцию, но не определять. Определить только конкретные специализации (не забываем, что для шаблонных функций запрещена частичная специализация, вместо неё используют перегрузки).
Пример:
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
 // В файле myprint.h
// Общая форма функции
template<typename T> void print(T value);
// Чтобы компилятор не пытался инстанциировать, пообещаем ему специализации
template<> void print<int>(int);
template<> void print<double>(double);
 
// В файле myprint.cpp
template<> void print<int>(int value)
{
    printf("%d", value);
}
 
template<> void print<double>(double value)
{
    printf("%f", value);
}
 
// в файле main.cpp
#include "myprint.h"
 
int main()
{
    const int a = 1;
    const double b = 2;
    print(a);
    print(b);
}
Добавлено через 9 минут
В C++11 есть такая вещь, как extern template, подавляющая неявную инстанциацию в надежде, что где-то есть явная.
popelyuk
 Аватар для popelyuk
8 / 8 / 1
Регистрация: 04.12.2012
Сообщений: 130
20.01.2013, 13:50  [ТС]     Шаблонные функции только для определённых типов! #6
Цитата Сообщение от Nick Alte Посмотреть сообщение
Объявить эту функцию, но не определять. Определить только конкретные специализации (не забываем, что для шаблонных функций запрещена частичная специализация, вместо неё используют перегрузки).
Пример:
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
 // В файле myprint.h
// Общая форма функции
template<typename T> void print(T value);
// Чтобы компилятор не пытался инстанциировать, пообещаем ему специализации
template<> void print<int>(int);
template<> void print<double>(double);
 
// В файле myprint.cpp
template<> void print<int>(int value)
{
    printf("%d", value);
}
 
template<> void print<double>(double value)
{
    printf("%f", value);
}
 
// в файле main.cpp
#include "myprint.h"
 
int main()
{
    const int a = 1;
    const double b = 2;
    print(a);
    print(b);
}
Добавлено через 9 минут
В C++11 есть такая вещь, как extern template, подавляющая неявную инстанциацию в надежде, что где-то есть явная.
Всё это конечно хорошо, но опять же теряется смысл в объявлении как template, ведь это по сути ничем не отличается от объявления двух перегруженных не template функций и если что-то нужно будет изменить придется менять в обоих, смысл тогда заморачиваться с template'ми?
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
20.01.2013, 13:53     Шаблонные функции только для определённых типов! #7
Цитата Сообщение от popelyuk Посмотреть сообщение
проблема состоит в том что если вызвать функцию как:
C++
1
std::cout<<"strToDouble="<<strToDouble("k")<<std::endl;
то подставляется const char вместо str_type
в данном случае подставляется const char[2]
Цитата Сообщение от popelyuk Посмотреть сообщение
а надо просто char, потому что тогда всё что внутри объявлено с типом str_type нельзя изменять что никоим образом мне не подходит!
а что вы хотите изменить?
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
20.01.2013, 14:06     Шаблонные функции только для определённых типов! #8
Цитата Сообщение от popelyuk Посмотреть сообщение
ведь это по сути ничем не отличается от объявления двух перегруженных не template функций
Ну почему же, никто не мешает использовать явную инстанциацию:
C++
1
2
3
4
5
6
7
8
9
10
11
12
// В myprint.h
extern template<typename T> void print(T value);
 
// В myprint.cpp
 
template<typename T> void print(T value)
{
    cout << value;
}
 
template void print<int>(int);
template void print<double>(double);
popelyuk
 Аватар для popelyuk
8 / 8 / 1
Регистрация: 04.12.2012
Сообщений: 130
20.01.2013, 14:17  [ТС]     Шаблонные функции только для определённых типов! #9
Цитата Сообщение от Jupiter Посмотреть сообщение
в данном случае подставляется const char[2]
ну насколько я знаю указатель не может быть 2 или 100 он просто указывает на первый элемент массива, ток что всё же const char
Цитата Сообщение от Jupiter Посмотреть сообщение
а что вы хотите изменить?
ну объявить например некоторое значении внутри template функции с типом str_type а потом изменить его:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
char *some_fun();
 
template <typename str_type>
int function(str_type *val);
//....
     str_type *some_val=some_fun();
     some_val[2]='k';// ошибка str_type=const char
 
}
 
int main () {
     function("const string");
     return 0;
}
Но, в общем, можете не парится я уже нашёл решение, выше написал.

Добавлено через 10 минут
Цитата Сообщение от Nick Alte Посмотреть сообщение
C++
1
2
template void print<int>(int);
template void print<double>(double);
в моём примере с const char и char это не работало вместо использования готовой специализации для char генерировалась для const char может быть с экстернами это по другому работает не знаю даже.
Цитата Сообщение от Nick Alte Посмотреть сообщение
C++
1
2
3
4
5
6
// В myprint.cpp
 
template<typename T> void print(T value)
{
    cout << value;
}
это что же теперь template implementation можно совать в .cpp файл по новым стандартам??
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
20.01.2013, 14:25     Шаблонные функции только для определённых типов! #10
Цитата Сообщение от popelyuk Посмотреть сообщение
это что же теперь template implementation можно совать в .cpp файл по новым стандартам??
Налицо явное непонимание. Цель была не дать пользователю создавать инстанциации самому. Для этого функцию объявляем, но не определяем. Все разрешённые инстанциации создаются в отдельном .cpp. Для этого в нём определяем шаблон нашей функции и создаём явные инстанциации для int и double. Это полноценные самостоятельные функции несмотря на то, что созданы из шаблона, поэтому они линкуются с вызовами, сделанными из других .cpp, где доступно только объявление.
I.M.
 Аватар для I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
20.01.2013, 14:32     Шаблонные функции только для определённых типов! #11
Цитата Сообщение от popelyuk Посмотреть сообщение
Как сделать чтобы для шаблонной функции генерировались только экземпляры для нескольких заданных типов, а остальные не генерировались?
Такая тема уже не раз поднималась. в новом стандарте так и не ввели средства для этого. Поэтому можно изгаляться по-разному. Например, сделать статик ассерт на все типы, кроме определенных.
popelyuk
 Аватар для popelyuk
8 / 8 / 1
Регистрация: 04.12.2012
Сообщений: 130
20.01.2013, 14:34  [ТС]     Шаблонные функции только для определённых типов! #12
Цитата Сообщение от Nick Alte Посмотреть сообщение
Налицо явное непонимание. Цель была не дать пользователю создавать инстанциации самому. Для этого функцию объявляем, но не определяем. Все разрешённые инстанциации создаются в отдельном .cpp. Для этого в нём определяем шаблон нашей функции и создаём явные инстанциации для int и double. Это полноценные самостоятельные функции несмотря на то, что созданы из шаблона, поэтому они линкуются с вызовами, сделанными из других .cpp, где доступно только объявление.
Цель была не совсем такая, нужно объявить template функцию (один раз!), а потом как-то описать под какие типы её можно генерить, а под остальные чтобы она сама не генерировалсь, вот!
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
20.01.2013, 14:41     Шаблонные функции только для определённых типов! #13
Цитата Сообщение от popelyuk Посмотреть сообщение
Цель была не совсем такая, нужно объявить template функцию (один раз!), а потом как-то описать под какие типы её можно генерить, а под остальные чтобы она сама не генерировалсь, вот!
Это то же самое абсолютно. Способ решения я и привёл: описываем функцию и инстанциируем её для всех нужных типов в отдельной единице трансляции. Эти инстанциации доступны для линкера, а создать новые инстанциации в других модулях невозможно, потому что определение шаблона функции этим модулять не доступно, у них есть только объявление. Заметим: во втором примере функция описана один раз, а инстанциируется два раза, для двух разрешённых типов.

Добавлено через 2 минуты
Видимо, источник взаимного непонимания - как раз явная инстанциация.
Конструкция
C++
1
template void print<int>(int);
- не объявление функции, а приказ её явно инстанциировать из шаблона для типа int. Объявление выглядело бы как
C++
1
template <> void print<int>(int);
popelyuk
 Аватар для popelyuk
8 / 8 / 1
Регистрация: 04.12.2012
Сообщений: 130
20.01.2013, 15:13  [ТС]     Шаблонные функции только для определённых типов! #14
У меня на это матерится:
C++
1
extern template <typename T> void print(T value);
Говорит что:
D:\Dropbox\source\test\test.h:2: error: expected unqualified-id before '<' token
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
20.01.2013, 15:43     Шаблонные функции только для определённых типов! #15
Так то ж из C++11. Попробуй без слова extern.
popelyuk
 Аватар для popelyuk
8 / 8 / 1
Регистрация: 04.12.2012
Сообщений: 130
20.01.2013, 16:02  [ТС]     Шаблонные функции только для определённых типов! #16
Цитата Сообщение от Nick Alte Посмотреть сообщение
Так то ж из C++11. Попробуй без слова extern.
да, теперь всё компилируется, но наверно я всё же чего-то не понимаю, а самое главное не понимаю чего именно я не понимаю! Я просто думал что определения темплейт функций должны быть всегда в хедерах и никогда в .cpp файлах, иначе что-то будет, а что будет? Подскажите ,пожалуйста, что мне прочитать чтобы "получить просветление" так сказать???

Добавлено через 1 минуту
только не советуйте "курить стандарт", как мне где-то тут или не тут советовали, чего-то не очень длинное желательно
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
20.01.2013, 16:05     Шаблонные функции только для определённых типов! #17
вот на мой взгляд одна из лучших книг по шаблонам в плюсах:
http://www.ozon.ru/context/detail/id/3960662/
хоть и до новостандартная, все равно очень хорошая.
в ней есть в частности глава 10 про инстанцирование.
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
20.01.2013, 16:46     Шаблонные функции только для определённых типов! #18
Цитата Сообщение от popelyuk Посмотреть сообщение
Я просто думал что определения темплейт функций должны быть всегда в хедерах и никогда в .cpp файлах, иначе что-то будет, а что будет?
Это не религиозная догма. Содержимое шаблонов быть в заголовках, чтобы их можно было инстанциировать: для этого ведь необходимо знать содержимое шаблона. Ведь что такое инстанциация? Берём шаблон void printf<T>(T) (который сам по себе не функция, а только заготовка для создания функций), подставляем туда конкретные типы (ну или константы) и на выходе получаем конкретный тип или конкретную функцию: void print<int>(int). А потом - другую функцию, формально совершенно независимую от первой: void print<double>(double).

То есть, мы выносим определение шаблона в отдельный файл и там же инстанциируем всё, что нам нужно. В результате этот файл по сути содержит набор уже окончательных функций. Обращение к таким функциям происходит как и к любым другим, через механизм связывания (через линкер). Для обращения к функции надо лишь знать типы аргументов и возвращаемого значения: объявление этой функции.

Так что при определении шаблонов внутри .cpp это "иначе что-то будет" сводится к невозможности инстанциировать шаблоны вне тех .cpp, в которых они объявлены. Что обычно противоречит нашим намерениям, но в данном случае - именно то, что доктор прописал.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.01.2013, 16:51     Шаблонные функции только для определённых типов!
Еще ссылки по теме:

C++ Шаблонные функции
Шаблонные функции C++
Шаблонные функции в C++ C++

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

Или воспользуйтесь поиском по форуму:
popelyuk
 Аватар для popelyuk
8 / 8 / 1
Регистрация: 04.12.2012
Сообщений: 130
20.01.2013, 16:51  [ТС]     Шаблонные функции только для определённых типов! #19
Цитата Сообщение от Nick Alte Посмотреть сообщение
Это не религиозная догма. Содержимое шаблонов быть в заголовках, чтобы их можно было инстанциировать: для этого ведь необходимо знать содержимое шаблона. Ведь что такое инстанциация? Берём шаблон void printf<T>(T) (который сам по себе не функция, а только заготовка для создания функций), подставляем туда конкретные типы (ну или константы) и на выходе получаем конкретный тип или конкретную функцию: void print<int>(int). А потом - другую функцию, формально совершенно независимую от первой: void print<double>(double).

То есть, мы выносим определение шаблона в отдельный файл и там же инстанциируем всё, что нам нужно. В результате этот файл по сути содержит набор уже окончательных функций. Обращение к таким функциям происходит как и к любым другим, через механизм связывания (через линкер). Для обращения к функции надо лишь знать типы аргументов и возвращаемого значения: объявление этой функции.

Так что при определении шаблонов внутри .cpp это "иначе что-то будет" сводится к невозможности инстанциировать шаблоны вне тех .cpp, в которых они объявлены. Что обычно противоречит нашим намерениям, но в данном случае - именно то, что доктор прописал.
теперь всё понятно, спасибо за уделённое время!
Yandex
Объявления
20.01.2013, 16:51     Шаблонные функции только для определённых типов!
Ответ Создать тему
Опции темы

Текущее время: 09:58. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru