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

шаблоны - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 24, средняя оценка - 4.79
LosAngeles
Заблокирован
31.07.2011, 11:36     шаблоны #1
возник вопрос, а как можно сделать так, чтобы различные экземпляры шаблона класса вели себя по разному в зависимости от того, что было передано в аргументах - класс или некласс. Приведу пример

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename T>
class Class {
  private:
 
    template<typename C> bool func(C const& x, C const& y, int C::*)
    {
        return true;
    }
 
    template<typename C> bool func(...)
    {
        return false;
    }
 
  public:
    bool operator()(T const& lhs, T const& rhs)
    {
        return func<T>(lhs, rhs, 0);
    }
};
пример конечно неважный, но суть ясна - в зависимости от того, что подставлять заместо Т этот недофунктор ведёт себя по разному. Пользователь не видит ужасного быдлокода между строками 5-13 и это радует, но не совсем. Я тут подумал может как то присобачить можно этот пример из книжки по шаблонам:
C++
1
2
3
4
5
6
7
8
9
10
11
12
template<typename T>
class IsClassT {
  private:
    typedef char One;
    typedef struct { char a[2]; } Two;
    template<typename C> static One test(int C::*);
 
    template<typename C> static Two test(...);
  public:
    enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
    enum { No = !Yes };
};
вдруг я ещё захочу пятьсот классов написать, а такой синтаксис нагоняет тоску... Можно как-то эти Yes и No присобачить заместо int C::*?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.07.2011, 11:36     шаблоны
Посмотрите здесь:

шаблоны C++
«Шаблоны шаблонов» vs «шаблоны с параметрами-шаблонами». C++
Шаблоны в C++ C++
Шаблоны C++
C++ Шаблоны
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Overmind024
99 / 99 / 6
Регистрация: 10.09.2010
Сообщений: 267
31.07.2011, 11:44     шаблоны #2
а что по твоему не класс?? структуры и стандартные типы???
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
31.07.2011, 11:54     шаблоны #3
Цитата Сообщение от Overmind024 Посмотреть сообщение
а что по твоему не класс?? структуры и стандартные типы???
Не хочется снова раздувать многостраничное обсуждение, но структура — это класс
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
31.07.2011, 12:04     шаблоны #4
если я тебя правильно понял, то так:
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
#include <iostream>
 
template<typename T>
struct is_pod {
   static const bool value = false;
};
 
template<>
struct is_pod<char> { static const bool value = true; };
template<>
struct is_pod<signed char> { static const bool value = true; };
template<>
struct is_pod<unsigned char> { static const bool value = true; };
template<>
struct is_pod<short> { static const bool value = true; };
template<>
struct is_pod<unsigned short> { static const bool value = true; };
template<>
struct is_pod<int> { static const bool value = true; };
template<>
struct is_pod<unsigned int> { static const bool value = true; };
template<>
struct is_pod<long> { static const bool value = true; };
template<>
struct is_pod<unsigned long> { static const bool value = true; };
template<>
struct is_pod<long long> { static const bool value = true; };
template<>
struct is_pod<unsigned long long> { static const bool value = true; };
 
template<bool ok, typename T>
struct real_func {
   static bool apply() {
      std::cout << __PRETTY_FUNCTION__ << std::endl;
      return ok;
   }
};
 
// ручная специализация для POD`ов
template<typename T>
struct real_func<true, T> {
   static bool apply() {
      std::cout << __PRETTY_FUNCTION__ << std::endl;
      return true;
   }
};
 
int main() {
   std::cout << std::boolalpha << real_func<is_pod<char>::value, char>::apply() << std::endl;
   std::cout << std::boolalpha << real_func<is_pod<std::ostream>::value, std::ostream>::apply() << std::endl;
}
http://liveworkspace.org/code/8553d9...f4ace00c4a332d

зы
тема вообще-то не для раздела новичков

Добавлено через 42 секунды
Цитата Сообщение от grizlik78 Посмотреть сообщение
но структура — это класс
угу. в с++ иначе быть не может.

Добавлено через 50 секунд
LosAngeles, надеюсь как использовать этот type_traits сам разберешься?

Добавлено через 51 секунду
и вообще-то, для этого написано огромное кол-шаблонов на все случаи жизни: http://www.boost.org/doc/libs/1_47_0...tml/index.html
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
31.07.2011, 12:15     шаблоны #5
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
struct mystruct {
};
 
class myclass {
    myclass(int);
};
 
int main()
{
    std::cout << std::boolalpha << std::is_pod<mystruct>().value << '\n'
              << std::boolalpha << std::is_pod<myclass>().value << '\n'
              << std::boolalpha << std::is_class<mystruct>().value << '\n'
              << std::boolalpha << std::is_class<myclass>().value << '\n';
    return 0;
}
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
31.07.2011, 12:17     шаблоны #6
Maxwe11, ну а POD-то тут к чему? Убери конструктор из класса и добавь к структуре, и вывод для is_pod изменится на противоположный.
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
31.07.2011, 12:18     шаблоны #7
Цитата Сообщение от Maxwe11 Посмотреть сообщение
std::is_class<myclass>()
зачем ты создаешь объекты compile-time шаблонов?
LosAngeles
Заблокирован
31.07.2011, 12:22  [ТС]     шаблоны #8
Цитата Сообщение от niXman Посмотреть сообщение
если я тебя правильно понял, то так:
да что-то типа того, но я надеялся как то автоматизировать процесс.
я как то так хотел сделать
C++
1
2
template<typename T, bool b = IsClassT<T>::Yes >
class Class;
и написать потом всего две специализации, но видимо не катит, потому что b зависит от Т. Да и все варианты не предусмотришь, как быть если мне понадобятся char* int* double****? Придётся ещё писать для них специализации. Понятно, что задача абстрактная, врядли мне это понадобится. Все эти is_pod и is_class хороши но я хочу именно на этапе компиляции отрезать не нужные ветки кода, я ещё подумал про #if\#else но ничего у меня не получилось с ними(
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
31.07.2011, 12:22     шаблоны #9
Цитата Сообщение от grizlik78 Посмотреть сообщение
Убери конструктор из класса и добавь к структуре, и вывод изменится на противоположный.
я и не спорю

Цитата Сообщение от niXman Посмотреть сообщение
зачем ты создаешь объекты compile-time шаблонов?
а как иначе?
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16827 / 5248 / 321
Регистрация: 30.03.2009
Сообщений: 14,132
Записей в блоге: 26
31.07.2011, 12:27     шаблоны #10
Цитата Сообщение от LosAngeles Посмотреть сообщение
да что-то типа того, но я надеялся как то автоматизировать процесс
Прежде, чем что-то автоматизировать, поставь внятно вопрос. Если я правильно понял (да и остальные тоже), то тебе нужно разделить на "скалярные типы" и "составные типы" или чего?
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
31.07.2011, 12:27     шаблоны #11
Цитата Сообщение от LosAngeles Посмотреть сообщение
я надеялся как то автоматизировать процесс.
специализации тебе придется писать руками. а дальше на основе их проксируй необходимую реализацию.

Цитата Сообщение от LosAngeles Посмотреть сообщение
как быть если мне понадобятся char* int* double****?
тоже специализировать руками

Цитата Сообщение от Maxwe11 Посмотреть сообщение
а как иначе?
так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
struct mystruct {
};
 
class myclass {
};
 
int main()
{
    std::cout << std::boolalpha << std::is_pod<mystruct>::value << std::endl
              << std::boolalpha << std::is_pod<myclass>::value << std::endl
              << std::boolalpha << std::is_class<mystruct>::value << std::endl
              << std::boolalpha << std::is_class<myclass>::value << std::endl;
    return 0;
}
http://liveworkspace.org/code/611cf2...f9f0c6fc62e33c

т.к. "результат" этих шаблонов известен еще на стадии компиляции.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16827 / 5248 / 321
Регистрация: 30.03.2009
Сообщений: 14,132
Записей в блоге: 26
31.07.2011, 12:30     шаблоны #12
Цитата Сообщение от Evg Посмотреть сообщение
Если я правильно понял (да и остальные тоже), то тебе нужно разделить на "скалярные типы" и "составные типы" или чего?
Если оно так, то я бы написал два разных шаблона: один для скалярных типов, один для составных. А в месте использования, там где я знаю, с каким типом работаю, использовал бы первый или второй. Это не очень красиво, но технически, как мне кажется, проще, чем работать с кучей специализаций, особенно если шаблон будет постоянно развиваться
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
31.07.2011, 12:33     шаблоны #13
специализация для указателей:
C++
1
2
3
4
5
6
7
8
9
template<class T>
struct is_pointer {
   static const bool value = false;
};
 
template<class T>
struct is_pointer<T*> {
   static const bool value = true;
};
и комбинируй вместе с is_pod<>, тогда сможешь определить, является ли указатель, указателем на под.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
31.07.2011, 12:34     шаблоны #14
Цитата Сообщение от niXman Посмотреть сообщение
т.к. "результат" этих шаблонов известен еще на стадии компиляции.
про это я в курсе, и даже сначала так и написал но студия меня чего-то непоняла)
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
31.07.2011, 12:35     шаблоны #15
Цитата Сообщение от Evg Посмотреть сообщение
как мне кажется, проще, чем работать с кучей специализаций
я и не предлагал кучу конечных специализаций. их должно быть две. но чтоб компилятору объяснить кто POD а кто нет, придется руками написать специализации шаблона is_pod<> для POD`ов.
LosAngeles
Заблокирован
31.07.2011, 12:38  [ТС]     шаблоны #16
Цитата Сообщение от niXman Посмотреть сообщение
тоже специализировать руками
жаль, я ещё попытался добавить операцию деления Ну то есть Yes это же единица, а No это 0, я думал тогда компилятор выберет наиболее подходящий шаблон, в котором деления на ноль нету, однако потом вычитал, что SFINAE на неправильные вычисления не распространяется, а жаль((
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16827 / 5248 / 321
Регистрация: 30.03.2009
Сообщений: 14,132
Записей в блоге: 26
31.07.2011, 12:41     шаблоны #17
Цитата Сообщение от niXman Посмотреть сообщение
я и не предлагал кучу конечных специализаций. их должно быть две. но чтоб компилятору объяснить кто POD а кто нет, придется руками написать специализации шаблона is_pod<> для POD`ов.
А... понятно...
В итоге получается что можно сделать и так и сяк, один фиг оба решения по сути череж..ные
niXman
Эксперт C++
 Аватар для niXman
3133 / 1445 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
31.07.2011, 12:43     шаблоны #18
Цитата Сообщение от Evg Посмотреть сообщение
череж..ные
да. так и живем
все равно, с++ лучший ЯП в мире
Overmind024
99 / 99 / 6
Регистрация: 10.09.2010
Сообщений: 267
31.07.2011, 13:16     шаблоны #19
Можно и без шаблонов

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
#include <iostream>
#include <typeinfo>
 
template<class T>
struct IsClass 
{
    bool operator() ()
    {
        const char* str = typeid(T).name();
        return (((strstr(str,"class") != NULL) || (strstr(str,"struct") != NULL)) && ( *(str+strlen(str) - 1) != '*'));
    }
};
 
int main()
{
    std::cout << std::boolalpha << IsClass<int>()() << std::endl;
    std::cout << std::boolalpha << IsClass<std::ostream>()() << std::endl;
    std::cout << std::boolalpha << IsClass<std::ostream*>()() << std::endl;
 
    std::cin.get();
    std::cin.get();
 
    return 0;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.07.2011, 13:22     шаблоны
Еще ссылки по теме:

Помогите писать на С++ через шаблоны. Консуле я писал, но надо писать исползуя шаблоны C++
C++ Шаблоны C++11
C++ Шаблоны в C++

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

Или воспользуйтесь поиском по форуму:
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
31.07.2011, 13:22     шаблоны #20
Без шаблонов не интересно.
Мне кажется, изначально хотелось чего-то вроде этого:
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
#include <iostream>
 
template<typename T>
class IsClassT {
  private:
    typedef char One;
    typedef struct { char a[2]; } Two;
    template<typename C> static One test(int C::*);
    
    template<typename C> static Two test(...);
  public:
    enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
    enum { No = !Yes };
};
 
template<typename T>
class Class {
  private:
 
    template <typename C, bool>
    struct Internal
    {
        static
        bool func(C const& x, C const& y)
        {
            return true;
        }
    };
 
    template <typename C>
    struct Internal<C, false>
    {
        static
        bool func(C const& x, C const& y)
        {
            return false;
        }
    };
 
  public:
    bool operator()(T const& lhs, T const& rhs)
    {
        return Internal<T, IsClassT<T>::Yes>::func(lhs, rhs);
    }
};
 
 
class A
{
};
 
int main()
{
    Class<A> c1;
    Class<int> c2;
 
    A a1, a2;
    int i1, i2;
 
    std::cout << "result with class A: " << std::boolalpha << c1(a1, a2) << std::endl;
    std::cout << "result with int: " << std::boolalpha << c2(i1, i2) << std::endl;
 
    return 0;
}
Если бы была разрешена частичная специализация шаблонов-функций, то внутренняя структура, наверное, не понадобилась бы.
Yandex
Объявления
31.07.2011, 13:22     шаблоны
Ответ Создать тему

Метки
полиморфизм, шаблоны, шаблоны полиморфизм
Опции темы

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