tags:

views:

73

answers:

1

How do I say:

template<typename T>
class X {
  // if T has method x(), define
  //   Y x() { return t.x() }

  T t;
};
+3  A: 

Just define it.

If X::x isn't called, then T::x doesn't have to exist either. If X::x is called and T::x doesn't exist, the error message will point to the use of X::x. Most compilers would use wording along the lines of: "Unknown identifier x while compiling Y X<Something>::x(void) within this context: whatever called X::x() for a Something that doesn't support it".

EDIT: Since you're using C++0x, by all means use decltype:

template<typename T>
class Forwards {
     T t;
public:
    decltype(this->t.x()) x() { return this->t.x(); }
};

I'm not 100% sure about whether to use decltype(T::x()), decltype(t.x()), or decltype(this->t.x()), but I'm pretty sure this should work. If t doesn't supply x, then the Forwards::x() function wouldn't be able to be instantiated. This still isn't perfect forwarding, since you need to know the argument list a-priori, but now you can deal with return type variation.

Ben Voigt
I was wondering if that was the pattern. Thanks for confirming. (I guess this means that you can't forward two functions with conflicting return types though.)
Neil G
C++0x brings `decltype` which will enable that. I don't know any non-invasive way to do it in C++03 though.
Ben Voigt
@Neil G: What is it that you really want to achieve? A single class cannot have more than one method differing only in the return type, but you can have different return values in different instantiations of the template (and/or different specializations)
David Rodríguez - dribeas
@David Rodríguez: I have a set of classes X_1, X_2, ... I have a template class Y<T>, which I apply to X_i, and which adds members and methods. (Y<X_i> has a member variable x of type X_i.) Some of the X_i implement interface Z. I would like Y<X_i> to implement interface Z through its member x if and only if X_i implements Z. That makes sense, right? Now suppose that there's a second interface W, which has a function with the same name and signature as in Z, but with a different return value. Now it's impossible to conditionally forward both interfaces.
Neil G
@Ben Voigt: I am using C++0x.
Neil G
@Neil: See edit with a suggestion on `decltype`.
Ben Voigt
@Ben Neat. Thanks.
Neil G
using "this" in the return type will fail. Instead you can use `t.x()` directly (unqualified lookup will find it). "this" is only visible in member function bodies or constructor initializer lists.
Johannes Schaub - litb