Ошибка создания фиктивного параметра шаблона C ++ при использовании typedef в производном классе шаблона

Я пытаюсь исправить странную ошибку, которую я имею с этим кодом. Это минимальный пример, который может повторить ошибку:

test11.cpp:

namespace detail{
template <auto UInt>
class Test{
public:
typedef decltype(UInt) value_type;

Test (const value_type& x = 0);

protected:
value_type n;
};

template<auto UInt>
Test<UInt>::Test (const value_type& x) : n(x){}

// Here, void would be substitute with some enable_if stuff
template <auto UInt, typename = void>
class TestChild : public Test<UInt>{
public:
typedef typename Test<UInt>::value_type value_type;

TestChild (const value_type& x = 0);
value_type foo() const;
};

template<auto UInt>
TestChild<UInt>::TestChild (const value_type& x) : Test<UInt>(x){}

template<auto UInt>
value_type TestChild<UInt>::foo(){
value_type ret=42;
return ret;
}
}

int main(){}

Я скомпилировал его, используя GCC 7.2.0 и Clang 5.0.0 в Ubuntu 16.04 LTS. Вы можете увидеть эти две ссылки для демонстраций:

Это сообщение об ошибке в gcc:

test11.cpp:27:38: error: ‘value_type’ does not name a type
TestChild<UInt>::TestChild (const value_type& x) : Test<UInt>(x){}
^~~~~~~~~~
test11.cpp:27:51: error: invalid use of incomplete type ‘class detail::TestChild<UInt>’
TestChild<UInt>::TestChild (const value_type& x) : Test<UInt>(x){}
^
test11.cpp:18:10: note: declaration of ‘class detail::TestChild<UInt>’
class TestChild : public Test<UInt>{
^~~~~~~~~
test11.cpp:30:4: error: ‘value_type’ does not name a type
value_type TestChild<UInt>::foo(){
^~~~~~~~~~

Кроме того, что действительно странно для меня, так это то, что, если я опущу фиктивный параметр в шаблоне для класса TestChild (Я имею в виду, template<auto UInt> вместо template<auto UInt, typename = void>), Я все еще получаю (более короткую) ошибку, которая выглядит так:

test11.cpp:30:4: error: ‘value_type’ does not name a type
value_type TestChild<UInt>::foo(){
^~~~~~~~~~

Вы можете проверить демо для GCC 7.2.0 Вот.

Похоже, главная ошибка в том, что, если я определяю функции вне класса, typedef typename Test<UInt>::value_type value_type; на самом деле не обнаружено (не знаю, хорошо ли я объяснил).

Это будет иметь смысл для меня, если это также произойдет, когда я определю функции внутри класса, но это не так, потому что в последнем случае все прекрасно компилируется (вы можете увидеть это в демонстрация если хотите).

В заключение, мой главный вопрос заключается в том, что я хочу скомпилировать эту программу, но с учетом того, что я должен отделить декларацию от определения. Итак, последняя демонстрация, которую я показал (где все определено внутри класса) — это то, чего я хочу достичь, но модульность.

Я надеюсь, что кто-то может мне помочь и объяснить, что происходит с этим кодом.

1

Решение

Вы должны сделать три (как минимум) изменения.

Первый: добавьте второе (по умолчанию) значение шаблона для TestChild,

Так

//................vvvvvvvvvvvv
template<auto UInt, typename V>
TestChild<UInt, V>::TestChild (const value_type& x) : Test<UInt>(x){}
//............^^^

и то же самое для foo() метод

Второе: запомни это foo() является const

Так

template <auto UInt, typename V>
value_type TestChild<UInt, V>::foo() const {
value_type ret=42;  // ...........^^^^^
return ret;
}

В-третьих: для типа возврата для foo() явный класс

Так typename TestChild<UInt, V>::value_type вместо value_type

template <auto UInt, typename V>
typename TestChild<UInt, V>::value_type TestChild<UInt, V>::foo() const {
value_type ret=42;
return ret;
}

Или, если вы предпочитаете, вы можете использовать auto ... -> синтаксис возвращаемого типа

template<auto UInt, typename V>
auto TestChild<UInt, V>::foo() const -> value_type {
value_type ret=42;
return ret;
}

или просто auto (но также в объявлении метода)

auto foo() const;

// ...

template<auto UInt, typename V>
auto TestChild<UInt, V>::foo() const {
value_type ret=42;
return ret;
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]