std :: declval против crtp, не может вывести тип возврата метода из неполного типа - PullRequest
12 голосов
/ 07 июня 2019

Я пытаюсь сделать что-то вроде этого (в C ++ 11):

#include <utility>

template <typename T>
struct base {
    using type = decltype( std::declval<T>().foo() );
};

struct bar : base<bar> {
    int foo() { return 42;}
};

int main() {
    bar::type x;
}

, который завершается ошибкой с

prog.cc: In instantiation of 'struct base<bar>':
prog.cc:8:14:   required from here
prog.cc:5:46: error: invalid use of incomplete type 'struct bar'
     using type = decltype( std::declval<T>().foo() );
                            ~~~~~~~~~~~~~~~~~~^~~
prog.cc:8:8: note: forward declaration of 'struct bar'
 struct bar : base<bar> {
        ^~~

Как я могу объявить псевдоним длятип возврата bar::foo в base?Разве это не возможно?

Этот вопрос, кажется, довольно связан: Специальное поведение для оператора вызова типа decltype для неполных типов , хотя мне не удалось применить ответ, данный таммое дело.

1 Ответ

12 голосов
/ 07 июня 2019

Вы можете сделать type псевдонимом типа шаблона, чтобы пользователи могли создавать его экземпляры после того, как доступно определение bar.Это изменит окончательный синтаксис с bar::type на bar::type<>.

template <typename T>
struct base {
    template <typename G = T>
    using type = decltype( std::declval<G>().foo() );
};

struct bar : base<bar> {
    int foo() { return 42;}
};

int main() {
    bar::type<> x;
}

живой пример на godbolt.org

...