vendredi 28 août 2015

Inheriting typedefs?

I've been confused recently by a few code examples -- sometimes it seems that inheriting typedefs exposed by a base class works, and sometimes it seems that it doesn't.

My questions are

  • Why doesn't it always work?
  • What are the situations that it will / won't work?
  • What are the good workarounds when it doesn't work?

Here's some specific code:

// First example: Inheriting `static const int ...`
// Basic TypeList object
template<typename... Ts>
struct TypeList {
    static const int size = sizeof...(Ts);
};

// Repeat metafunction
template<typename T>
struct repeat;

template<typename... Ts>
struct repeat<TypeList<Ts...>> : TypeList<Ts..., Ts...> {};

// Checks
typedef TypeList<int, float, char> MyList;

static_assert(MyList::size == 3, "D:");
static_assert(repeat<MyList>::size == 6, "D:");


// Second example: Inheriting typedefs
// Meta function to compute a bundle of types
template <typename T>
struct FuncPtrTypes {
    typedef int result_type;
    typedef T input_type;
    typedef result_type(*func_ptr_type)(input_type);
};


// template <typename T, typename FuncPtrTypes<T>::func_ptr_type me>
// struct FuncPtr : FuncPtrTypes<T> {
//     static result_type apply(input_type i) {
//         return me(i);
//     }
// };
//
// Doesn't compile (?): clang 3.6:
// main.cpp:34:9: error: unknown type name 'result_type'
//         static result_type apply(input_type i) {
//                ^
// main.cpp:34:27: error: unknown type name 'input_type'
//         static result_type apply(input_type i) {
//                                  ^
//
// g++ 4.8.4:
// main.cpp:34:9: error: ‘result_type’ does not name a type
//   static result_type apply(input_type i) {
//          ^
// main.cpp:34:9: note: (perhaps ‘typename FuncPtrTypes<T>::result_type’ was intended)


// This compiles but is clumsy:

template <typename T, typename FuncPtrTypes<T>::func_ptr_type me>
struct FuncPtr {
    typedef typename FuncPtrTypes<T>::input_type input_type;
    typedef typename FuncPtrTypes<T>::result_type result_type;

    static result_type apply(input_type i) {
        return me(i);
    }
};


// A non-template example:
struct foo {
    typedef int bar;
};

struct baz : foo {};

typedef baz::bar bazbar;
// ^ This compiles... huh??

int main() {}

Aucun commentaire:

Enregistrer un commentaire