Konstruktor für spezielle Typen "Umleiten"?
-
Ja hatte da n Denkfehler. Hiermit gehts:
template <class Iter> struct DisableInt : public boost::disable_if<boost::is_integral<Iter>, char> {};
-
Dravere schrieb:
Nur dass es problematisch ist, weil es unter MSVC zum Beispiel auch Spezialisierungen für
std::iterator_traitsfürint,double,float,long,short, usw. gibt. Daher funktioniert dies auch nicht ... Es gibt eben keine Möglichkeit einen Iterator zu erkennen.Das ist komisch. Weisst du wozu es diese Spezialisierungen gibt?
Aber mal davon abgesehen... könnte man sich nicht zu nutze machen dass in dem Fall
Iterundstd::iterator_traits<Iter>::value_typeder selbe Typ sind?Ich muss sagen, als ich enable_if vorgeschlagen habe, bin ich einfach davon ausgegangen, dass es recht einfach möglich sein muss
is_iteratorzu implementieren, da es jastd::iterator_traitsgibt.Irgendwie ziemlich doof dass es doch nicht so einfach ist

-
hustbaer schrieb:
Irgendwie ziemlich doof dass es doch nicht so einfach ist

Ich schätze mal wenns so einfach wäre gäbs bei boost auch ein is_iterator oder ähnliches. Es gibt in der Mailing-List schon eine längere Diskussion zu dem Thema:
-
hustbaer schrieb:
Das ist komisch. Weisst du wozu es diese Spezialisierungen gibt?
Nicht die Bohne einer Ahnung! Es steht nicht mal hier etwas:
http://msdn.microsoft.com/en-us/library/zdxb97eh.aspxIch weiss es selber nur, weil ich mal etwas über
std::iterator_traitslösen wollte und dabei voll auf die Schnauze gefallen bin. Vor allem habe ich zuerst ziemlich lange gesucht, bis ich gemerkt habe, dass da zusätzliche Spezialisierungen vorhanden sind. Ich wäre niemals auf diese Idee gekommen
Hey ... moment mal ... würde sowas nicht gehen?
template<typename CategoryT> struct isValidIteratorCategory { enum ( value = 0 }; }; template<> struct isValidIteratorCategory<std::input_iterator_tag> { enum { value = 1; }; }; template<> struct isValidIteratorCategory<std::output_iterator_tag> { enum { value = 1; }; }; template<> struct isValidIteratorCategory<std::forward_iterator_tag> { enum { value = 1; }; }; template<> struct isValidIteratorCategory<std::bidirectional_iterator_tag> { enum { value = 1; }; }; template<> struct isValidIteratorCategory<std::random_access_iterator_tag> { enum { value = 1; }; }; template<typename IterT> struct IsIterator { enum { value = isValidIteratorCategory<typename std::iterator_traits<IterT>::iterator_category>::value }; }; template<typename T> struct IsIterator<T*> { enum { value = 1; }; }; template<typename T> struct IsIterator<T const*> { enum { value = 1; } };Oder überseh ich etwas?
Grüssli
-
Dravere schrieb:
Oder überseh ich etwas?
class Alien {}; int main() { cout << IsIterator<Alien>::value; }Das ist dann möglicherweise der Grund, weshalb Spezialisierungen für int&co. eingeführt werden, um nicht schon iterator_traits<int>::iterator_category auszusteigen, sondern ggf. das Ergebnis per sfinae zu verwerten.
vielleicht so
typedef char no; typedef no yes[2]; no& tag_test(...); template <typename T> yes& tag_test(const T&, iterator_traits<T>::iterator_category*=0); template <typename T> struct has_tag : mpl::bool_<sizeof(tag_test(*(T*)0))==sizeof(yes)> {}; typedef mpl::vector<input_iterator_tag,output_iterator_tag,forward_iterator_tag,random_access_iterator_tag> valid_tags; template <typename T, bool = has_tag<T>::value> struct is_iterator : mpl::contains<valid_tags,T> {}; template <typename T> struct is_iterator< T, false> : mpl::bool_<false> {};
-
Wenn ich das richtig sehe brauch ich noch nichtmal den Dummy-Parameter - folgendes compiliert bei mir:
template <class T> struct DisableInt : public boost::disable_if<boost::is_integral<T>, T>{}; void foo(int i, short l) { cout << "integral" << endl; } template<class I> void foo(I first, typename DisableInt<I>::type last) { cout << "iterator" << endl; } int main() { int a[] = {1, 2, 3, 4, 5}; std::vector<int> vec(a, a+5); foo(3, 6); //integral foo(a, a+5); //iterator foo(vec.begin(), vec.end()); //iterator }Gibts irgendwelche Fallen in die ich da tappen könnte oder ist das ok?
-
foo(0.0,0.0);(is_arithmetic ist etwas besser, aber auch hier finden sich Ausnahmen)
Compilierbarkeit als solche ist generell nicht das Problem, da es bei nicht-Template- vs. Templatefunktion nicht zu Mehrdeutigkeiten kommen kann.Den 2. Typen nicht zu deduzieren, erlaubt Konvertierungen für diesen. Zum Beispiel könnte man einen const_iterator mit einem nicht-const-Iterator kombineren. Das ist zumindest unerwartet und könnte auf einen Fehler beim Aufruf hindeuten. Zudem gibt einige defekte Implementationen, die die Initialiserung von Iteratoren mit Zeigern zulassen, so dass dann so etwas wie
foo(it,0);zulässig wäre. An der Stelle halte ich den Verzicht auf den Dummy-Parmeter für ungünstig, man verzichtet auf eine rigidere Prüfung und das Interface wird selbst unübersichtlich und schwer verständlich. Im Falle eines Dummy-Parameters ist dagegen klar, was echte Parameter sind, und welcher Teil nur zur Überprüfung/Overloadauflösung dient.
-
camper schrieb:
foo(0.0,0.0);(is_arithmetic ist etwas besser, aber auch hier finden sich Ausnahmen)
Da es bei der nicht-Templatefunktion um einen myContainer::size_type geht, der immer integral ist, darf 0.0 gerne auf Fehler laufen, weis kein Iterator ist.
camper schrieb:
Den 2. Typen nicht zu deduzieren, erlaubt Konvertierungen für diesen.
Guter Einwand, also doch den dummy. Danke
