template<typename T>
struct S
{
typedef T resultT;
void foo(resultT&t);
};
template<typename T>
void xxx_foo(typename S<T>::resultT&t)
{
t = T();
}
void xxx_foo(S<double>::resultT&t)
{
t = -1;
}
template<typename T>
void S<T>::foo(typename S<T>::resultT&t)
{
xxx_foo<T>(t);
}
int main()
{
double dd;
S<double> s;
s.foo(dd);
S<void*> s2 ;
void* vp;
s2.foo(vp);
cout << dd << endl << vp;
return 0;
}
нужно на выходе получить -1 для double и значение по умолчанию для всех остальных. При этом используется не сам тип double в сигнатуре функций, а локальный typedef, который по воле случая к нему приводится.
Этот частный случай можно обойти. Вопрос как вообще это правильно делается?
Речь идёт о том когда для некоторых шаблонных функций нужна спецяльная реализация, и для остальных общая, но при этом типы заданы через typedef.
Здравствуйте, Caracrist, Вы писали:
C>нужно на выходе получить -1 для double и значение по умолчанию для всех остальных. При этом используется не сам тип double в сигнатуре функций, а локальный typedef, который по воле случая к нему приводится.
C>Этот частный случай можно обойти. Вопрос как вообще это правильно делается?
C>Речь идёт о том когда для некоторых шаблонных функций нужна спецяльная реализация, и для остальных общая, но при этом типы заданы через typedef.
Частичных специализаций функций вроде как нет в языке. Попробуйте использовать частичную специализацию классов:
template<typename T> struct xxx;
template<typename U>
struct xxx<S<U>>
{
static void foo(U &t)
{
t = U();
}
};
template<>
struct xxx<S<double>>
{
static void foo(double &t)
{
t = -1;
}
};
template<typename T>
void S<T>::foo(typename S<T>::resultT &t)
{
xxx<S<T>>::foo(t);
}
Здравствуйте, Caracrist, Вы писали:
C>C>template<typename T>
C>struct S
C>{
C>typedef T resultT;
C>void foo(resultT&t);
C>};
C>template<typename T>
C>void xxx_foo(typename S<T>::resultT&t)
C>{
C>t = T();
C>}
C>void xxx_foo(S<double>::resultT&t)
C>{
C>t = -1;
C>}
C>template<typename T>
C>void S<T>::foo(typename S<T>::resultT&t)
C>{
C>xxx_foo<T>(t);
C>}
C>int main()
C>{
C>double dd;
C>S<double> s;
C>s.foo(dd);
C>S<void*> s2 ;
C>void* vp;
C>s2.foo(vp);
C>cout << dd << endl << vp;
C>return 0;
C>}
C>
C>нужно на выходе получить -1 для double и значение по умолчанию для всех остальных. При этом используется не сам тип double в сигнатуре функций, а локальный typedef, который по воле случая к нему приводится.
C>Этот частный случай можно обойти. Вопрос как вообще это правильно делается?
C>Речь идёт о том когда для некоторых шаблонных функций нужна спецяльная реализация, и для остальных общая, но при этом типы заданы через typedef.
#include <iostream>
using namespace std;
template<typename T>
class A{
public:
typedef T resultT;
void m(typename A<T>::resultT &e);
};
template<typename T>
void A<T>::m(typename A<T>::resultT &e){
e= 0;
}
template<>
class A<double>{
public:
typedef double resultT;
void m(A<double>::resultT &m);
};
void A<double>::m(resultT &m){
m = -1;
}
int _tmain(int argc, _TCHAR* argv[])
{
int t1;
A<int> a;
a.m(t1);
double t2;
A<double> b;
b.m(t2);
cout << t1 << " " << t2 << endl;
system("PAUSE");
return 0;
}
Так пойдёт?
Здравствуйте, Caracrist, Вы писали:
Ты мастер вопросы формулировать, конечно. Тебе нужно получить -1 для всех double и его typedefов или только для дабла. Если первое, то
template<typename T>
struct TypeWrapper
{
typedef typename T myType;
myType default()
{
return myType();
}
};
template<typename T>
TypeWrapper<T> typeReasoner(const typename T& value)
{
return TypeWrapper<T>();
}
struct TypeFramework
{
template<typename T>
TypeFramework(const typename TypeWrapper<T>& function)
{
printf("random type \n");
};
TypeFramework(const TypeWrapper<double>& function)
{
printf("double type \n");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
typedef double hiddenType;
double a;
hiddenType b;
void* c;
TypeFramework(typeReasoner(a));
TypeFramework(typeReasoner(b));
TypeFramework(typeReasoner(c));
return 0;
}
Здравствуйте, Caracrist, Вы писали:
C>нужно на выходе получить -1 для double и значение по умолчанию для всех остальных. При этом используется не сам тип double в сигнатуре функций, а локальный typedef, который по воле случая к нему приводится.
В смысле, тебе нужно получить -1 если шаблон параметризован double?
template<class T> struct resetter
{
template<class V> static void reset(V& v) { v = V(); }
};
template<> struct resetter<double>
{
template<class V> static void reset(V& v) { v = -1; }
};
// или так
template<class T> struct initializer
{
template<class V> static V init() { return V(); }
};
template<> struct initializer<double>
{
template<class V> static void init() { return -1; }
};
....
template<class T> struct S : resetter<T>
{
void foo()
{
.....
X x = initializer<T>::init<X>(); // если не унаследовались от инструмента
// либо
X x;
reset(x); // если унаследовались от инструмента
.....
};
Есть нюансы, связанные с наличием у типа переменной различных конструкторов и операторов присваивания (т.е. можно ли инициализировать и присваивать -1). Если речь идёт только о числовых типах, тогда всё равно, а если о каких-нибудь рукодельных, то нужно уточнить контракт. В зависимости от этого, лучше будет использовать initializer или resetter.
C>Этот частный случай можно обойти. Вопрос как вообще это правильно делается?
C>Речь идёт о том когда для некоторых шаблонных функций нужна спецяльная реализация, и для остальных общая, но при этом типы заданы через typedef.
Лично я — за то, чтобы не устраивать кашу из специализаций внутри шаблона, а вытащить специализируемый код в отдельный шаблон. Что, собственно, и показал.