C++ статический полиморфизм (CRTP) и использующий определения типов от производных классов

Я прочитал статью Wikipedia о любопытно повторяющемся шаблонном шаблоне в C++ для того, чтобы сделать статичный (чтение: время компиляции) полиморфизм. Я хотел обобщить его так, чтобы я мог изменить типы возврата функций на основе производного типа. (Это кажется, что должно быть возможно, так как базовый тип знает производный тип от шаблонного параметра). К сожалению, следующий код не скомпилирует использование MSVC 2010 (у меня нет легкого доступа к gcc прямо сейчас, таким образом, я еще не попробовал его). Кто-либо знает почему?

template 
class base {
public:
    typedef typename derived_t::value_type value_type;
    value_type foo() {
        return static_cast(this)->foo();
    }
};

template 
class derived : public base > {
public:
    typedef T value_type;
    value_type foo() {
        return T(); //return some T object (assumes T is default constructable)
    }
};

int main() {
    derived a;
}

BTW, у меня есть обходное решение с помощью дополнительных шаблонных параметров, но мне не нравится он---, это станет очень подробным при передаче многих типов цепочка наследования.

template 
class base { ... };

template 
class derived : public base,T> { ... };

Править:

Сообщение об ошибке, что MSVC 2010 дает в этой ситуации, error C2039: 'value_type' : is not a member of 'derived'

g ++ 4.1.2 (с помощью codepad.org) говорит error: no type named 'value_type' in 'class derived'

61
задан 4 September 2014 в 13:44

1 ответ

Я знаю, что это - в основном обходное решение, которое Вы нашли, и не любите, но я хотел зарегистрировать его и также сказать, что это - в основном текущее решение этой проблемы.

я искал способ сделать это некоторое время и никогда не находил хорошее решение. То, что это не возможно, является причиной почему в конечном счете, вещи как boost::iterator_facade<Self, different_type, value_type, ...> потребность много параметров.

, Конечно, мы хотели бы, чтобы что-то что-то вроде этого работало:

template<class CRTP> 
struct incrementable{
    void operator++(){static_cast<CRTP&>(*this).increment();}
    using ptr_type = typename CRTP::value_type*; // doesn't work, A is incomplete
};

template<class T>
struct A : incrementable<A<T>>{
    void increment(){}
    using value_type = T;
    value_type f() const{return value_type{};}
};

int main(){A<double> a; ++a;}

, Если это было возможно, все черты производного класса могли бы быть переданы неявно ot базовый класс. Идиома, которую я нашел для получения того же эффекта, должна передать черты базовому классу полностью.

template<class CRTP, class ValueType> 
struct incrementable{
    void operator++(){static_cast<CRTP&>(*this).increment();}
    using value_type = ValueType;
    using ptr_type = value_type*;
};

template<class T>
struct A : incrementable<A<T>, T>{
    void increment(){}
    typename A::value_type f() const{return typename A::value_type{};}
//    using value_type = typename A::value_type;
//    value_type f() const{return value_type{};}
};

int main(){A<double> a; ++a;}

https://godbolt.org/z/2G4w7d

недостаток состоит в том, что к черте в производном классе нужно получить доступ с квалифицированным typename, или повторно включил using.

0
ответ дан 31 October 2019 в 16:16

Другие вопросы по тегам:

Похожие вопросы: