template spezialisierung und integrale typen
-
hallo,
ich möchte für eine template-member funktion eine spezialisierung für integrale typen schreiben. das problem ist, dass diese vom compiler nur genutzt wird, wenn wirklich exakt der angegebene typ genutzt wurde, für impliziet konvertierbare typen wird die allgemeine template-funktion genutzt.
das mag zwar noch nachvollziehbar sein, mich verwundert allerdings, wie das in der implementation von list.insert vom gcc gezaubert wurde, dort steht nämlich:void insert(iterator __position, size_type __n, const value_type& __x) { list __tmp(__n, __x, _M_get_Node_allocator()); splice(__position, __tmp); } template<typename _InputIterator> void insert(iterator __position, _InputIterator __first, _InputIterator __last) { list __tmp(__first, __last, _M_get_Node_allocator()); splice(__position, __tmp); }und der compiler ist durchaus schlau genug die erste variante aufzurufen, auch wenn value_type = int ist und __x von einem anderen integralen typ konvertiert wird sowie __n nicht explizit nach size_type gecastet wurde.
hier mein beispiel:
#include <cstdlib> #include <list> using namespace std; struct S{ int x; }; template <typename T> class C{ public: template <typename T2> void foo(T2 i){ i.x = 0; } void foo(size_t i){ } }; int main(){ for(int i = 0, j = 0; true; ++i, ++j); C<int> c; c.foo((size_t)0); //funktioniert c.foo(0); //funktioniert nicht, versucht template-fkt. zu verwenden list<int> l; l.insert(l.end(), 5, 5); //funktioniert l.insert(l.end(), (int)5, (size_t)5); //funktioniert l.insert(l.end(), (long long)5, (long long)5); //funktioniert }
-
hmm, zu unverständlich formuliert?

edit: problem gelöst. tiefer im code der STL sind überladungen für alle 13 integer typen versteckt

-
13? Also mit allen
typedefs, oder?
-
also das sieht dann so aus:
template<typename _Tp> struct __is_integer { enum { __value = 0 }; typedef __false_type __type; }; // Thirteen specializations (yes there are eleven standard integer // types; 'long long' and 'unsigned long long' are supported as // extensions) template<> struct __is_integer<bool> { enum { __value = 1 }; typedef __true_type __type; }; // usw...und den __type nutzt man dann als übergabe-parameter um die passende überladung der funktion aufzurufen.
-
Interessiert mich gerade, wie man auf dreizehn kommt...

So?
bool unsigned char signed char unsigned wchar_t signed wchar_t unsigned short signed short unsigned int signed int unsigned long signed long unsigned long long signed long long
-
// Thirteen specializations (yes there are eleven standard integer // types; 'long long' and 'unsigned long long' are supported as // extensions)guckst du INCLUDEDIR/bits/cpp_type_traits.h falls du einen GCC zur hand hast.
-
Nexus schrieb:
Interessiert mich gerade, wie man auf dreizehn kommt...

So?
bool unsigned char signed char unsigned wchar_t signed wchar_t unsigned short signed short unsigned int signed int unsigned long signed long unsigned long long signed long longfast. wchar_t kennt keine signed/unsigned-Zusätze (welche Variante zutrifft, hängt vom Compiler ab). Aber du hast auch char als eigenständigen Typ vergessen.
-
hmm, und wchar_t ist wohl nicht auf jedem compiler verfügbar, es ist zum heulen...
-
camper schrieb:
Aber du hast auch char als eigenständigen Typ vergessen.
Danke für die Erklärung; ich wusste nicht, dass
charin drei Variationen vorkommt. Ich dachte einfach, es sei systemabhängig, ob er in seiner Standardformsignedoderunsignedist.
-
Nexus schrieb:
camper schrieb:
Aber du hast auch char als eigenständigen Typ vergessen.
Danke für die Erklärung; ich wusste nicht, dass
charin drei Variationen vorkommt. Ich dachte einfach, es sei systemabhängig, ob er in seiner Standardformsignedoderunsignedist.Es ist system- und compilerabhängig, ob char vorzeichenbehaftet ist oder nicht, das ist richtig. Trotzdem sind char und der entsprechend qualifizierte un/signed char zwei verschiedene Typen. In der Hinsicht unterscheidet sich un/signed char von den anderen Typen, wo die signed-qualifikation weggelassen werden kann.