Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.02.2012, 09:44   #1
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию шаблонные методы шаблона. Специализация.

Вопрос: каким образом можно вынести реализацию методов класса за его пределы?

Изначально вопрос формулировался так: Каким образом можно произвести специализацию одного из методов шаблона класса так, что бы эта специализация зависела только от одного (или нескольких) параметров шаблона, но не от всех?

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

Однако, ответ на этот вопрос был найден. Ниже представленный код этот момент иллюстрирует:

Код:
struct SEmpty;

template<int ID, class tK, class tR>
class TTest
{
private:
    template<int IDS> int WorkEx();
    template<> int WorkEx<0>() { std::cout<<"0\n"; return 0; }
    template<> int WorkEx<1>() { std::cout<<"1\n"; return 0; }
private:
    template<int IDS, class tKK> int WorkEx1();
    template<> int WorkEx1<0, SEmpty>() { std::cout<<"0, empty\n"; return 0; }
public: 
    int Work()  { return WorkEx<ID>();      }
    int Work1() { return WorkEx1<ID, tK>(); }
};

int main()
{
    TTest<0,SEmpty,int>test;  
    test.Work();   //вывод: 0
    test.Work1();  //вывод: 0, empty
}
Способ заключается в том, что бы делегировать вызов другому шаблонному методу, который можно специализировать целиком.

Но я не люблю, когда у меня декларативная часть класса захламляется реализациями методов.

Вопрос: каким образом можно вынести реализацию методов класса за его пределы?

Вообще, всегда думал, что правильно - сначала пишется шапка класса-владельца, потом пишется шапка шаблонного метода. Использовал такой способ:

Код:
template<int ID, class tK, class tR>
    template<> 
        int TTest<ID, tK,tR>::WorkEx<0>() { std::cout<<"0\n"; return 0; }
//: error C2768: TTest<ID,tK,tR>::WorkEx: недопустимое использование явных аргументов шаблона
В чем я ошибаюсь?
Вообще, я уже как мартышка методом научного тыка по всякому перепробовал. Если специализировать внутри класса - все нормально. Снаружи ну никак не получается...
_Bers вне форума Ответить с цитированием
Старый 07.02.2012, 21:28   #2
pproger
C++ hater
СтарожилДжуниор
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2_Bers
для начала нужно сказать, что твой код неверный. по стандарту (с++2003) нельзя специализировать шаблонный член внутри шаблонного класса. в студии своя религия, поэтому у тебя это компилится.

Цитата:
Вопрос: каким образом можно вынести реализацию методов класса за его пределы?
а специализация шаблонного метода и должна быть ТОЛЬКО вынесенной. но внешный класс тоже нужно специализировать

Код:
#include <iostream>

using namespace std;

template <typename T, typename U>
class A {
public:
	template <int i> void foo();
};

template <typename T, typename U>
template <int i>
void A<T, U>::foo()
{
	cout << i << endl;
}

template <>
template <>
void A<int, char>::foo<0>()
{
	cout << "zero" << endl;
}

int main()
{
	A<int, char> a;
	a.foo<0>();

	return 0;
}
Цитата:
В чем я ошибаюсь?
Вообще, я уже как мартышка методом научного тыка по всякому перепробовал
в том, что нельзя специализировать член, не специализировав внешний класс)

Цитата:
как можно частично специализировать отдельно взятый метод шаблона
нет такого понятия, как ЧАСТИЧНАЯ специализация шаблонного метода/функции. есть только ПОЛНАЯ специализация и перегрузка.

но в плюсах всегда можно извратиться, и сэмулировать то, что тебе нужно

Код:
#include <iostream>

using namespace std;

// шаблонный класс хранит общий метод
template <typename T, typename U, int i>
class FooDelegate {
public:
	static void foo()
	{
		cout << i << endl;
	}
};

// специализированный шаблонный класс
template <typename T, typename U>
class FooDelegate<T, U, 0> {
public:
	static void foo()
	{
		cout << "zero" << endl;
	}
};

template <typename T, typename U>
class A {
public:
	template <int i>
	void foo()
	{
                // делегируем вызов
		FooDelegate<T, U, i>::foo();
	}
};

int main()
{
	A<int, char> a;
	a.foo<0>();

	return 0;
}
ну вот так например.

читать александреску, вандервуда
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Старый 07.02.2012, 22:08   #3
pproger
C++ hater
СтарожилДжуниор
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

можно даже пойти дальше, написав
Код:
#include <iostream>

using namespace std;

template <template <typename, typename> class A, typename T, typename U, int i>
class FooDelegate {
public:
	static void foo(A<T, U> *a)
	{
		cout << i << endl;
		a->bar();
	}
};

template <template <typename, typename> class A, typename T, typename U>
class FooDelegate<A, T, U, 0> {
public:
	static void foo(A<T, U> *a)
	{
		cout << "zero" << endl;
	}
};

template <typename T, typename U>
class A {
public:
	template <int i>
	void foo()
	{
		FooDelegate< ::A, T, U, i>::foo(this);
	}

private:
	void bar() const
	{
		cout << "inner method called" << endl;
	}

	template <template <typename, typename> class A, typename, typename, int>
	friend class FooDelegate;
};

int main()
{
	A<int, char> a;
        a.foo<0>();	
        a.foo<1>();

	return 0;
}
эмулируем передачу указателя this

извратиться можно сильно, но не всегда нужно. уверен на 99%, твою задачу можно решить проще. только не говори, что задача - частично специализировать шаблонный метод (как ты упорно настаивал в прошлой теме). это НЕ задача, а средство реализации. напиши, что хочешь получить в итоге, я может смогу показать, как это бы сделал я. если же "задача" - использовать как можно больше шаблонов - флаг в руки.
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance

Последний раз редактировалось pproger; 07.02.2012 в 22:11.
pproger вне форума Ответить с цитированием
Старый 08.02.2012, 00:47   #4
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

В вашем коде я нефига не понял вот этот момент:
Код:
template <int i>
	void foo()
	{
		FooDelegate< ::A, T, U, i>::foo(this); //<--- что за разрешение контекста ::A ?
	}

Коллективный разум подсказал альтернативное решение.
И хотя сие суть "обходной путь", но оно полностью удовлетворяет условию.
То бишь, сие суть "имитация" частичной специализации отдельного метода шаблона класса.

Если интересно:

Код:
struct SEmpty{}; 
 
template<int ID, class tK, class tR> struct TBase { static int Work() { std::cout<<"ID\n";      return 0; } };
 
template<class tK, class tR> struct TBase<0, tK, tR>  { static int Work() { std::cout<<"0\n";       return 0; } };
 
template<class tR> struct TBase<0, SEmpty, tR>  { static int Work() { std::cout<<"0 empty\n"; return 0; } };
 
template<int ID, class tK, class tR> class TTest: TBase<ID, tK, tR> { public: int Work(); };

template<int ID, class tK, class tR>  int TTest<ID, tK,tR>::Work(){ return TBase<ID, tK, tR>::Work(); }
 
int main()
{
    TTest<1, SEmpty, int>test1; test1.Work();  
    TTest<0, int,    int>test2; test2.Work();  
    TTest<0, SEmpty, int>test3; test3.Work();  
}

Последний раз редактировалось _Bers; 08.02.2012 в 00:52.
_Bers вне форума Ответить с цитированием
Старый 08.02.2012, 00:52   #5
pproger
C++ hater
СтарожилДжуниор
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2_Bers
Цитата:
В вашем коде я нефига не понял вот этот момент:
шланг хотел, чтоб передаваемый шаблонный параметр находился в пространстве имен. вот я и указал на глобальное. гцц было насрать

Цитата:
Если интересно:
и чем это отличается от моего варианта?))) тем, что у тебя хреново отформатировано?) а ну да, у тебя еще структура вместо класса для делегирования статичного метода. гениальные люди...

пс. и да, мой код все же ближе к твоему "идеалу". ты просто перенес шаблонные параметры из шаблонного метода в шаблонный класс. я их оставил.

сравни твой вызов:
Код:
TTest<1, SEmpty, int>test1;
test1.Work();  
TTest<0, int,    int>test2;
test2.Work();
и мой:
Код:
A<int, char> a;
a.foo<0>();	
a.foo<1>();
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance

Последний раз редактировалось pproger; 08.02.2012 в 00:58.
pproger вне форума Ответить с цитированием
Старый 08.02.2012, 01:38   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от pproger Посмотреть сообщение
2_Bers
и чем это отличается от моего варианта?)))
сравни твой вызов:

Код:
TTest<1, SEmpty, int>test1;test1.Work();  
TTest<0, int,    int>test2;   test2.Work();
и мой:
Код:
A<int, char> a;a.foo<0>();	
a.foo<1>();
Клиент не знает "какого он типа". Он не знает, что ему нужно толкнуть foo<0>, или foo<1>
Он просто толкает foo.

foo "как бы специализирована" для каждого конкретного случая. Но клиенты об этом ничего не знают, и им это даже и не интересно.

Вся служебная информация о фактических типах конструируется один раз при создании класса объекта. И в последствии больше нигде не фигурирует. Клиенты не знают, что они имеют дело с продуктами шаблона.
_Bers вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Специализация шаблона Bubaleh Общие вопросы C/C++ 6 09.09.2011 12:01
Шаблоны класса и специализация РагнаР Общие вопросы C/C++ 9 13.03.2011 19:29
шаблонные строковые функции MrKarapuz Общие вопросы C/C++ 7 09.11.2009 15:07
C++ Специализация шаблона opensuse2008 Помощь студентам 7 07.06.2009 18:00