template-argumente einer basisklasse extrahieren
-
hi
in meiner klassenhierarchie leiten ne menge klassen von derselben basisklasse ab. diese basisklasse ist eigentlich ein klassentemplate. da ich in der funktion f mit dem template-argument der basisklasse arbeiten möchte muss ich das irgendwie extrahieren
template<int v> struct base { }; template<typename T> void f(T const& x) { //brauche hier x.base<>::v als compile-time-konstante (damit ich es an ein anderes template übergeben kann) }andererseits kann ich die signatur nicht in
f(base<v> const&)ändern, da die abgeleiteten klassen gewisse methoden implementieren, die ich innerhalb von f auch noch brauche (ich brauche den übergebenen typen einfach...).kann ich das irgendwie bewerkstelligen, ohne dass v in abgeleiteten klassen zugänglich ist? (ja, die unmittelbar ableitenden klassen kennen v ohnehin, aber der "stammbaum" ist ziemlich gross und hat viele "generationen")
-
hanstroll123 schrieb:
andererseits kann ich die signatur nicht in
f(base<v> const&)ändernaber als Hilfsfunktion taugt das.
template<int v> struct base { }; template <int v> std::integral_constant<int,v> base_helper(base<v>&&); template<typename T> void f(T const& x) { constexpr auto v = decltype(base_helper(x))::value; }
-
guter ansatz, wollte gerade fragen wie ich das in c++03 machen kann, habe es aber schon selbst geschafft (vorsicht, gebastel):
#include <iostream> template<typename T> struct id { typedef T type; }; template<int v> struct sz_type : public id<char(&)[v]> {}; template<int v> struct base {}; struct fun : base<42> { void f() const { std::cout << "hello"; } }; template<int v> typename sz_type<v>::type help(base<v> const&); template<typename T> void f(T const&x) { x.f(); base<sizeof(help(x))>(); } int main() { f(fun()); }jetzt nur noch für nicht-positive int's, hmm vll. zweierkomplement selbst anwenden.
-
template <int v> std::integral_constant<int,v> base_helper(base<v>&&); template<typename T> void f(T const& x) { constexpr auto v = decltype(base_helper(x))::value; }
Ich glaube langsam du wirst Meschugge.Mit C++03 sieht das Ganze so aus:
template <typename> struct extract; template <int v> struct extract<base<v>> {static int const value = v;}; template<typename T> void f(T const& x) { std::cout << extract<T>::value; } int main() { f(base<4>()); }
-
Arcoth schrieb:
Ich glaube langsam du wirst Meschugge.Macht Spass, solltest du auch mal versuchen.
Arcoth schrieb:
Mit C++03 sieht das Ganze so aus:
template <typename> struct extract; template <int v> struct extract<base<v>> {static int const value = v;}; template<typename T> void f(T const& x) { std::cout << extract<T>::value; } int main() { f(base<4>()); }langweilig
-
Da du mein #1-Vorbild bist habe ich wohl keine Wahl als dir zu folgen.
template <int v> char(&foo(base<v>))[v]; template <typename T> void bar(T t) { std::cout << sizeof(foo(t)); }Besser?
-
Der Umweg über integral_constant in C++11 scheint mir eigentlich ein bisschen von hinten durch die Brust ins Auge geschossen. Mit constexpr geht es direkter:
#include <iostream> template<int v> struct base { }; struct derived : base<4> { }; // Wichtiger Teil hier template<int v> int constexpr f(base<v> const &) { return v; } // Wichtiger Teil zuende. int main() { derived d; std::cout << f(d) << '\n'; base<f(d) * 2> b; std::cout << f(b) << '\n'; }
-
seldon schrieb:
Der Umweg über integral_constant in C++11 scheint mir eigentlich ein bisschen von hinten durch die Brust ins Auge geschossen. Mit constexpr geht es direkter:
Das macht allerdings nicht den Funktionsaufruf zu einem konstanten Ausdruck, wenn das Argument nicht konstant ist.
include <iostream> template<int v> struct base { }; struct derived : base<4> { }; template<int v> int constexpr f(base<v> const &) { return v; } int main() { constexpr auto x = f(*new derived); // }
-
Arcoth schrieb:
Mit C++03 sieht das Ganze so aus:
template <typename> struct extract; template <int v> struct extract<base<v>> {static int const value = v;}; template<typename T> void f(T const& x) { std::cout << extract<T>::value; } int main() { f(base<4>()); }das ist nicht ganz das, was ich gesucht habe; T ist ein von base<v> abgeleiteter typ.
hat jemand eine bessere c++03-lösung als die meine?
-
Ups, tatsächlich, das war Quatsch.
Dann nimm die zweite von mir gepostete, die funktioniert.