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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
popelyuk
8 / 8 / 1
Регистрация: 04.12.2012
Сообщений: 130
#1

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

20.01.2013, 12:20. Просмотров 915. Ответов 18
Метки нет (Все метки)

Как сделать чтобы для шаблонной функции генерировались только экземпляры для нескольких заданных типов, а остальные не генерировались?
Следующее определение не помогает (в конце кода):
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'ности" ))
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.01.2013, 12:20
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Шаблонные функции только для определённых типов! (C++):

Можно ли сделать шаблон функции только для определенных типов? - C++
Например template&lt;typename T&gt; void func(T x){} Где T может быть только int,double и float

Шаблонные функции для заполнения массива - C++
Здравствуйте, уважаемое сообщество. Пожалуйста, помогите с решением задачи. Тема - шаблонные функции. Нужно написать функции для...

Шаблонные классы. Присвоение к указателю и приведение типов - C++
Добрый вечер, ув. форум, есть к вам вопрос. Есть род. абстрактный класс: ParentAbstact Есть два наследника: ChildOne : public...

Шаблонные функции для нахождения минимального и максимального элемента пары чисел - C++
Описать функции-шаблоны для нахождения минимального и максимального элемента пары чисел. Задано два целых и два действительные числа....

Написать шаблонные, перегруженные функции для ввода и вывода на экран массивов и матриц - C++
Добрый вечер всем! Помогите написать написать шаблонные, перегруженные функции input и output для ввода и вывода на экран массивов и...

Шаблонные функции - C++
Доброго времени суток. Есть шаблонная функция(двоичный сумматор прямого кода): template &lt;class T&gt; void Main_register::badc(T *regist, T...

18
gray_fox
What a waste!
1522 / 1227 / 70
Регистрация: 21.04.2012
Сообщений: 2,565
Завершенные тесты: 3
20.01.2013, 12:31 #2
Цитата Сообщение от popelyuk Посмотреть сообщение
о подставляется const char вместо str_type, а надо просто char
"k" - это строковый литерал, его символы костантны, поэтому и выводится const char, а не char. Почему бы просто не объявить in_add как str_type const*?
0
DU
1484 / 1130 / 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
0
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 функции генерировать только определённые инстанации?? И запрещать генерировать остальные?
0
Nick Alte
Эксперт С++
1642 / 1014 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 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, подавляющая неявную инстанциацию в надежде, что где-то есть явная.
0
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'ми?
0
Jupiter
Каратель
Эксперт С++
6561 / 3982 / 227
Регистрация: 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 нельзя изменять что никоим образом мне не подходит!
а что вы хотите изменить?
0
Nick Alte
Эксперт С++
1642 / 1014 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 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);
0
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 файл по новым стандартам??
0
Nick Alte
Эксперт С++
1642 / 1014 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
20.01.2013, 14:25 #10
Цитата Сообщение от popelyuk Посмотреть сообщение
это что же теперь template implementation можно совать в .cpp файл по новым стандартам??
Налицо явное непонимание. Цель была не дать пользователю создавать инстанциации самому. Для этого функцию объявляем, но не определяем. Все разрешённые инстанциации создаются в отдельном .cpp. Для этого в нём определяем шаблон нашей функции и создаём явные инстанциации для int и double. Это полноценные самостоятельные функции несмотря на то, что созданы из шаблона, поэтому они линкуются с вызовами, сделанными из других .cpp, где доступно только объявление.
0
I.M.
566 / 549 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
20.01.2013, 14:32 #11
Цитата Сообщение от popelyuk Посмотреть сообщение
Как сделать чтобы для шаблонной функции генерировались только экземпляры для нескольких заданных типов, а остальные не генерировались?
Такая тема уже не раз поднималась. в новом стандарте так и не ввели средства для этого. Поэтому можно изгаляться по-разному. Например, сделать статик ассерт на все типы, кроме определенных.
0
popelyuk
8 / 8 / 1
Регистрация: 04.12.2012
Сообщений: 130
20.01.2013, 14:34  [ТС] #12
Цитата Сообщение от Nick Alte Посмотреть сообщение
Налицо явное непонимание. Цель была не дать пользователю создавать инстанциации самому. Для этого функцию объявляем, но не определяем. Все разрешённые инстанциации создаются в отдельном .cpp. Для этого в нём определяем шаблон нашей функции и создаём явные инстанциации для int и double. Это полноценные самостоятельные функции несмотря на то, что созданы из шаблона, поэтому они линкуются с вызовами, сделанными из других .cpp, где доступно только объявление.
Цель была не совсем такая, нужно объявить template функцию (один раз!), а потом как-то описать под какие типы её можно генерить, а под остальные чтобы она сама не генерировалсь, вот!
0
Nick Alte
Эксперт С++
1642 / 1014 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 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);
0
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
0
Nick Alte
Эксперт С++
1642 / 1014 / 119
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
20.01.2013, 15:43 #15
Так то ж из C++11. Попробуй без слова extern.
0
20.01.2013, 15:43
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.01.2013, 15:43
Привет! Вот еще темы с ответами:

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

Шаблонные функции - C++
Такой код работает. #include &lt;iostream&gt; #include &lt;string&gt; #include &lt;cstring&gt; using namespace std; template &lt;typename T&gt; T...

Шаблонные функции - C++
1) Написать шаблонную функцию для нахождения минимального из трех передаваемых чисел (для чисел типа int, double, char). В функции...

Шаблонные функции в C++ - C++
Каждый раз когда вижу код, который должен быть простым и понятным, я понимаю его немного хуже. Вот наш код: template &lt;typename T,...


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

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

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