I am experimenting with the new features of C++11. In my setup I would really love to use inheriting constructors, but unfortunately no compiler implements those yet. Therefore I am trying to simulate the same behaviour. I can write something like this:
template <class T>
class Wrapper : public T {
    public:
    template <typename... As>
    Wrapper(As && ... as) : T { std::forward<As>(as)... } { }
    // ... nice additions to T ...
};
This works... most of the time. Sometimes the code using the Wrapper class(es) must use SFINAE to detect how such a Wrapper<T> can be constructed. There is however the following issue: as far as overload resolution is concerned, the constructor of Wrapper<T> will accept any arguments -- but then compilation fails (and this is not covered by SFINAE) if the type T cannot be constructed using those.
I was trying to conditionally enable the different instantiations of the constructor template using enable_if
    template <typename... As, typename std::enable_if<std::is_constructible<T, As && ...>::value, int>::type = 0>
    Wrapper(As && ... as) // ...
which works fine as long as:
T is public
T is not abstractMy question is: how to get rid of the above two constraints?
I tried to overcome the first by checking (using SFINAE and sizeof()) whether the expression new T(std::declval<As &&>()...) is well-formed within Wrapper<T>. But this, of course, does not work, because the only way a derived class can use its base's protected constructor is in the member initialization list.
For the second one, I have no idea whatsoever -- and it is the one I need more, because sometimes it is the Wrapper which implements the abstract functions of T, making it a complete type.
I want a solution which:
Thanks!
This appears to work fine on my local GCC (4.7, courtesy of rubenvb). GCC on ideone prints several "implemented" compiler internal errors though.
I had to make the "implementation details" of the Experiment class public, because for some reasons (which smells like a bug), my version of GCC complains about them being private, even though only the class itself uses it.
#include <utility>
template<typename T, typename Ignored>
struct Ignore { typedef T type; };
struct EatAll {
  template<typename ...T>
  EatAll(T&&...) {}
};
template<typename T>
struct Experiment : T {
public:
  typedef char yes[1];
  typedef char no[2];
  static void check1(T const&);
  static void check1(EatAll);
  // if this SFINAE fails, T accepts it
  template<typename ...U>
  static auto check(int, U&&...u)
    -> typename Ignore<no&, 
        decltype(Experiment::check1({std::forward<U>(u)...}))>::type;
  template<typename ...U>
  static yes &check(long, U&&...);
public:
  void f() {}
  template<typename ...U, 
           typename std::enable_if<
             std::is_same<decltype(Experiment::check(0, std::declval<U>()...)),
                          yes&>::value, int>::type = 0>
  Experiment(U &&...u):T{ std::forward<U>(u)... }
  {}
};
// TEST
struct AbstractBase {
  protected:
    AbstractBase(int, float);
    virtual void f() = 0;
};
struct Annoyer { Annoyer(int); };
void x(Experiment<AbstractBase>);
void x(Annoyer);
int main() {
  x({42});
  x({42, 43.f});
}
Update: The code also works on Clang.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With