000
09.07.2010, 13:12 Uhr
~ex-bart
Gast
|
Hi!
Ich habe eine Template-Klasse, die an einem ihrer Template-Parameter Methoden aufruft:
C++: |
template<typename T> struct caller { static void call(const T& t, int p1, int p2) { t.foo(p1, p2); } };
|
Problem ist, daß das auch für Template Parameter T funktionieren soll, wenn es nur die methode foo(int) gibt, dann soll der parameter p2 ignoriert werden, etwa so:
C++: |
template<typename T, bool cond = has_two_argument_foo<T>::value> struct caller { static void call(const T& t, int p1, int p2) { t.foo(p1, p2); } }; template<typename T> struct caller<T, false> { static void call(const T& t, int p1, int p2) { t.foo(p1); } };
|
Die Frage ist nun, wie das Template
C++: |
has_two_argument_foo
|
aussehen muß. Daß das ganze prinzipiell möglich ist, weiß ich, da es mit Boost.Typeof im Emulationsmodus geht:
C++: |
#define BOOST_TYPEOF_COMPLIANT #include <type_traits> #include <boost/typeof/typeof.hpp>
template<typename T> struct always_false : std::false_type { };
template<typename LOP, typename = std::false_type> struct has_two_argument_foo : public std::false_type { }; template<typename LOP> struct has_two_argument_foo<LOP, typename always_false<BOOST_TYPEOF_TPL(((LOP*)0)->foo(0,0))>::type > : public std::true_type { };
|
Diese Lösung hat allerdings zwei Probleme: erstens kann ich auf meiner Zielplattform nicht mit Boost rechnen, und zweitens funktioniert sie nicht, wenn der Rückgabetyp von foo() void ist. Ich habe erfolglos versucht, zu verstehen, was die typeof-Emulation tut, und das Dokument, das die Implementierung der typeof-Emulation beschreibt scheint nicht mehr zu existieren.
Kann mir jemand weiterhelfen?
Hier ist nochmal der Komplette code meines Testprograms. Übersetzen muß man das ganze mit "g++ --std=c++0x" oder so ähnlich, damit der compiler den header <type_traits> kennt.
C++: |
#include <iostream> #include <type_traits> #include <boost/typeof/typeof.hpp>
template<typename T> struct always_false : std::false_type { };
template<typename LOP, typename = std::false_type> struct has_two_argument_foo : public std::false_type { }; template<typename LOP> struct has_two_argument_foo<LOP, typename always_false<BOOST_TYPEOF_TPL(((LOP*)0)->foo(0,0))>::type > : public std::true_type { };
template<typename T, bool cond = has_two_argument_foo<T>::value> struct caller { static void call(T& t, int p1, int p2) { t.foo(p1, p2); } }; template<typename T> struct caller<T, false> { static void call(T& t, int p1, int p2) { t.foo(p1); } };
struct LOP1 { int foo(int a, int b) { std::cout << "LOP1 (two arguments)" << std::endl; return 0; } int foo(int a) { std::cout << "LOP1 (one argument)" << std::endl; return 0; } };
struct LOP2 { int foo(int a) { std::cout << "LOP2 (one argument)" << std::endl; return 0; } };
int main() { LOP1 lop1; LOP2 lop2; caller<LOP1>::call(lop1, 0, 1); caller<LOP2>::call(lop2, 0, 1); }
|
|