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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 25.06.2013, 17:19   #1
akhomyak2
Новичок
Джуниор
 
Регистрация: 25.06.2013
Сообщений: 3
По умолчанию Рекурсивная специализация шаблонов

Объясните, пожалуйста, почему код ниже компилируется в VC7.1, но не компилируется в VC9?

namespace aux {

template< typename > struct unused;

template<typename RootT, template< typename > class T0>
struct TrimUnused
{
typedef T0<
typename TrimUnused< RootT, unused >::Result
> Result;
};

template< typename RootT >
struct TrimUnused< RootT, unused >
{
typedef RootT Result;
};
}

template< typename T > struct A : public T
{
void check(char* p)
{
*p = 'A';
T::check(++p);
}
};

struct Root
{
void check(char* p)
{
*p = 'R';
}
};

//! Класс-наследник
struct D : public aux::TrimUnused< Root, A >::Result
{
typedef aux::TrimUnused< Root, A >::Result _BaseT;

void check(char* p)
{
*p = 'D';
_BaseT::check(++p);
}
};

int _tmain(int argc, _TCHAR* argv[])
{
char temp[32] = { 0 };
D d;
d.check(temp);

return 0;
}
akhomyak2 вне форума Ответить с цитированием
Старый 25.06.2013, 23:49   #2
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

похоже на баг студии
_Bers вне форума Ответить с цитированием
Старый 26.06.2013, 01:28   #3
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

лучше год студии писать...я не помню которая из них 9-ая.
и какие ошибки выдала она?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 26.06.2013, 02:30   #4
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
лучше год студии писать...я не помню которая из них 9-ая.
и какие ошибки выдала она?
У мя в 2008 залагала, а вот гцц сожрал сразу

Сама ошибка:
: error C3200: 'A<T>' : invalid template argument for template parameter 'T0', expected a class template


Причем, в коде:
http://codepad.org/evtcvanO

Код:
template< class T > struct unused;

template<class RootT, template< class T> class T0>struct TrimUnused
{
    typedef T0<typename TrimUnused< RootT, unused >::Result > Result;
};

template< class RootT >struct TrimUnused< RootT, unused >
{
    typedef RootT Result;
};


template< class T > struct A : T{   void check(char* p){ *p = 'A'; T::check(++p); }};
struct Root{  void check(char* p){*p = 'R';} };

//! Класс-наследник
struct D : public TrimUnused< Root, A >::Result
{
    typedef TrimUnused< Root, A >::Result _BaseT;            //<--- typedef ломает компиляцию. 
     //: error C3200: 'A<T>' : invalid template argument for template parameter 'T0', expected a class template


    void check(char* p){    *p = 'D';_BaseT::check(++p); } 
};

int main()
{
    typedef TrimUnused< Root, A > T1;   //<--- а вот здесь прокатывает на ура
    cout<<typeid(T1::Result).name()<<endl;
    char temp[32] = { 0 };
    D d;
    d.check(temp);
    return 0;
}
Видно, что сам по себе typedef синтаксически правильный, ибо объявленный в функции main отрабатывает корректно.

А так же тот факт, что гцц нормально переваривает, наводит на мысль, что сие есть баг студийного компиля.
_Bers вне форума Ответить с цитированием
Старый 26.06.2013, 15:18   #5
akhomyak2
Новичок
Джуниор
 
Регистрация: 25.06.2013
Сообщений: 3
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
лучше год студии писать...я не помню которая из них 9-ая.
и какие ошибки выдала она?
vc9 - vc 2008, также аналогичная ошибка выпадает и в vc 2010
akhomyak2 вне форума Ответить с цитированием
Старый 26.06.2013, 15:28   #6
akhomyak2
Новичок
Джуниор
 
Регистрация: 25.06.2013
Сообщений: 3
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
У мя в 2008 залагала, а вот гцц сожрал сразу

Сама ошибка:
: error C3200: 'A<T>' : invalid template argument for template parameter 'T0', expected a class template


Причем, в коде:
http://codepad.org/evtcvanO

...

Видно, что сам по себе typedef синтаксически правильный, ибо объявленный в функции main отрабатывает корректно.

А так же тот факт, что гцц нормально переваривает, наводит на мысль, что сие есть баг студийного компиля.
Да, поскольку вынос typedef aux::TrimUnused< Root, A >::Result _BaseT; за пределы класса D (например, перед классом D в примере ниже):
Код:
namespace aux {

	template< typename > struct unused;

	template<typename RootT, template< typename > class T0>
	struct TrimUnused
	{
		typedef T0<
			typename TrimUnused< RootT, unused >::Result
		> Result;
	};

	template< typename RootT >
	struct TrimUnused< RootT, unused >
	{
		typedef RootT Result;
	};
}

template< typename T > struct A : public T
{
	void check(char* p)
	{
		*p = 'A';
		T::check(++p);
	}
};

struct Root
{
	void check(char* p)
	{
		*p = 'R';
	}
};

typedef aux::TrimUnused< Root, A >::Result BaseT;

//! Класс-наследник
struct D : public BaseT
{
	void check(char* p)
	{
		*p = 'D';
		BaseT::check(++p);
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	char temp[32] = { 0 };
	D d;
	d.check(temp);

	std::cout << strcmp(temp, "DAR") << std::endl;
	return 0;
}
решает проблему, то, очевидно, имеет мест ошибка VC 2008 (и, кстати, и VC 2010, где аналогиная проблема).
akhomyak2 вне форума Ответить с цитированием
Старый 11.07.2013, 22:58   #7
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Если это ещё актуально: я запостил feedback по поводу этого жучка, и получил от майкрософт ответ:

Posted by Microsoft on 09.07.2013 at 23:27
Цитата:
Hi Kartonagnick,

Thank you for taking the time to provide your feedback. After reviewing your reported issue, in the context of all the issues reported to us, we have decided not to take any action on this feedback at this time. We will re-consider our decision for a future release.

If this issue is severe, causing critical business situations or blocking your product development or deployment, please go to http://support.microsoft.com or call 1-800-MICROSOFT for assistance.
For Microsoft premier customers, please contact your administrator, your Technical Account Manager, or your Microsoft premier account representative.

Thanks,
Karl Niu
Posted by Microsoft on 09.07.2013 at 23:27
Цитата:
The workaround is to use '::A' in the class definition. Change:

typedef TrimUnused< Root, A >::Result _BaseT;

to

typedef TrimUnused< Root, ::A >::Result _BaseT;
И в общем то, предложенный обходной путь действительно работает. И не противоречит стандарту:
http://codepad.org/hDK0Uo2g
_Bers вне форума Ответить с цитированием
Ответ


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



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