Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Что такое ABuse и Adv https://www.cyberforum.ru/ cpp/ thread2455458.html
Добрый вечер, может кто нибудь объяснить что такое ABuse и Adv? Какие функции выполняют эти библиотеки и где их достать вообще? ABuse.lib и Adv.lib
Записать в вектор количество двузначных элементов соответствующих столбцов матрицы C++
Дана матрица целых чисел D(N, M). Сформировать вектор S(M), в который записать количество двузначных элементов соответствующих столбцов матрицы. Вывести на экран номера строк, в которых максимальный...
Вывод списка разрешений для ключа реестра C++
Добрый вечер. Задали написать программу, которая выводит список разрешений для ключа реестра. Не знаю как осуществить. Буду благодарна за помощь.
C++ Класс, текстовый файл Помогите сделать программу, используя класс, подключение файла с данными!!!! Тема: Відомості про вкладників банку: номер особового рахунку, категорія вкладу, паспортні дані, поточна сума внеску,... https://www.cyberforum.ru/ cpp/ thread2454966.html
C++ Не находит экзешник проекта https://www.cyberforum.ru/ cpp/ thread2454857.html
Всем привет. Помогите, пожалуйста. Visual Studio 2019 выдаёт ошибку: "LNK1104 не удаётся открыть файл "...\TestCPPApp\Debug\TestCPPApp.exe"", хотя экзешник там находится.
C++ Как отключить (скрыть) курсор в консоли С++
Собственно, вопрос говорит сам за себя. Уже видел тему на эту тему ( масло масляное )), но мне не очень ясна тема с Хендлами. Почему-то конфликтуют два хендла, ( для курсора и для цветного вывода )...
Как запустить из моей проги другуя, чтобы моя старая закрылась через батник C++
Мне надо чтобы я запускал мою прогу, та запускала другую и batnik, batnik закрывается 1 прогу , а вторая прога спокойно работала. Вот код 1 проги. #include <iostream> #include <windows.h>...
C++ Реализация целочисленного деления в столбик Доброго времени суток, на повестке дня пришла задача реализовать целочисленное деление в столбик на си (можно и с++). То самое деление , что все мы проходили еще в начальной школе. Кому не трудно,... https://www.cyberforum.ru/ cpp/ thread2454492.html
C++ Считывание со строки и решение примера https://www.cyberforum.ru/ cpp/ thread2454335.html
Работаю с WindowsForms. Дана строка, я ввожу туда стандартный пример (к примеру "2+4-7+8-3"). И нажимаю на кнопку. Нужно написать код для кнопки который будет считывать цифры и знаки, решать этот...
C++ Как правильно построить структуру классов? Есть четыре объекта: ион1, ион2, атом, электрон. Каждый объект имеет свою массу, но движется по одинаковому алгоритму. Еще объекты рассеиваются, но по разному, хотя есть и пересечения в коде. ... https://www.cyberforum.ru/ cpp/ thread2454264.html
880 / 336 / 78
Регистрация: 17.05.2015
Сообщений: 1,051
0

Gtest, доступ к элементам базового класса-шаблона без указания параметров шаблона. баг или фича?

18.05.2019, 20:39. Показов 751. Ответов 4
Метки (Все метки)

Всем привет.

Продолжаю экспертизу gtest/gmock.

Количество ошибок и багов зашкаливает.

Ничего удивительного, учитывая то,
как плохо они тестирует собственный фреймворк для тестов.
У них всего два сервиса: на одном тестируется сборка gcc,
на другом - вижуал студия.

О том, что бы тестировать для всех заявленных платформ,
всеми заявленными компиляторами и речи не идет.

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

И вот, похоже, что теперь такая порочная практика привела к новой проблеме:
Нарушения легаси.

Фреймворк перестал собираться на старых линейках вижуал студии.

Следующий код иллюстрирует проблему:

https://rextester.com/FKX1017

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
 
template<class t> 
struct first
{
    using type = t;
};
 
template<class t> 
struct next : first<t>
{
    using type = typename next::first::type;
    
    type val = 333;
};
 
int main()
{
    next<int> sample;
    
    std::cout << "val = " << sample.val << '\n';
}
output:
Код
val = 333
Код прекрасно собирается и работает.
Не только gcc, но и новыми компиляторами от Visual Studio
Например, компилятор от Visual Studio 2015 update 3

Однако, вот эта строка немножко напрягает:
C++
1
using type = typename next::first::type;
Что об этом говорит стандарт языка?
С каких это пор можно обращаться к элементам шаблонно-класса,
без указания параметров шаблона?

Всегда думала, что опускать параметры шаблона класса
можно только для методов этого же класса.

Похоже, что более старые компиляторы (Visual Studio 2015 update 1)
рассуждают так же, как и я:

https://rextester.com/ACJ53272

Код
source_file.cpp(13): error C2039: 'first<int>': is not a member of 'next<int>'
source_file.cpp(20): note: see reference to class template instantiation 'next<int>' being compiled
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x64
Привожу код к более каноничному виду, и сборка завершается успехом:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
 
template<class t>
struct first
{
    using type = t;
};
 
 
template<class t>
struct next : first<t>
{
    using base = first<t>;
    using type = typename base::type;
    
    type val = 333;
};
 
int main()
{
    next<int> sample;
    
    std::cout << "val = " << sample.val << '\n';
}
Учитывая, что gtest прекрасно собирался и работал
на всей линейке студий начиная с 2008 (а может и 2003?)
Можно сделать неутешительный вывод:
поддержка фреймворка никакая.
за качество никто не отвечает.
количество багов растет.
качество кода - падает.
использование - на свой страх и риск.
и этот страх более чем обоснован.

фрагменты реального проблемного кода


файл: gtest-internal.h

https://rextester.com/OXKC11289

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <iostream>
 
// Backport of std::index_sequence.
template <size_t... Is>
struct IndexSequence {
  using type = IndexSequence;
};
 
// Double the IndexSequence, and one if plus_one is true.
template <bool plus_one, typename T, size_t sizeofT>
struct DoubleSequence;
template <size_t... I, size_t sizeofT>
struct DoubleSequence<true, IndexSequence<I...>, sizeofT> {
  using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>;
};
template <size_t... I, size_t sizeofT>
struct DoubleSequence<false, IndexSequence<I...>, sizeofT> {
  using type = IndexSequence<I..., (sizeofT + I)...>;
};
 
// Backport of std::make_index_sequence.
// It uses O(ln(N)) instantiation depth.
template <size_t N>
struct MakeIndexSequence
    : DoubleSequence<N % 2 == 1, typename MakeIndexSequence<N / 2>::type,
                     N / 2>::type {};
 
template <>
struct MakeIndexSequence<0> : IndexSequence<> {};
 
// FIXME: This implementation of ElemFromList is O(1) in instantiation depth,
// but it is O(N^2) in total instantiations. Not sure if this is the best
// tradeoff, as it will make it somewhat slow to compile.
template <typename T, size_t, size_t>
struct ElemFromListImpl {};
 
template <typename T, size_t I>
struct ElemFromListImpl<T, I, I> {
  using type = T;
};
 
// Get the Nth element from T...
// It uses O(1) instantiation depth.
template <size_t N, typename I, typename... T>
struct ElemFromList;
 
template <size_t N, size_t... I, typename... T>
struct ElemFromList<N, IndexSequence<I...>, T...>
    : ElemFromListImpl<T, N, I>... {};
 
template <typename... T>
class FlatTuple;
 
template <typename Derived, size_t I>
struct FlatTupleElemBase;
 
template <typename... T, size_t I>
struct FlatTupleElemBase<FlatTuple<T...>, I> {
  using value_type =
      typename ElemFromList<I, typename MakeIndexSequence<sizeof...(T)>::type,
                            T...>::type;
  FlatTupleElemBase() = default;
  explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {}
  value_type value;
};
 
template <typename Derived, typename Idx>
struct FlatTupleBase;
 
template <size_t... Idx, typename... T>
struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
    : FlatTupleElemBase<FlatTuple<T...>, Idx>... {
  using Indices = IndexSequence<Idx...>;
  FlatTupleBase() = default;
  explicit FlatTupleBase(T... t)
      : FlatTupleElemBase<FlatTuple<T...>, Idx>(std::move(t))... {}
};
 
// Analog to std::tuple but with different tradeoffs.
// This class minimizes the template instantiation depth, thus allowing more
// elements that std::tuple would. std::tuple has been seen to require an
// instantiation depth of more than 10x the number of elements in some
// implementations.
// FlatTuple and ElemFromList are not recursive and have a fixed depth
// regardless of T...
// MakeIndexSequence, on the other hand, it is recursive but with an
// instantiation depth of O(ln(N)).
template <typename... T>
class FlatTuple: private FlatTupleBase<FlatTuple<T...>, typename MakeIndexSequence<sizeof...(T)>::type> 
{
  using Indices = typename FlatTuple::FlatTupleBase::Indices;
 
 public:
  FlatTuple() = default;
  explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {}
 
  template <size_t I>
  const typename ElemFromList<I, Indices, T...>::type& Get() const {
    return static_cast<const FlatTupleElemBase<FlatTuple, I>*>(this)->value;
  }
 
  template <size_t I>
  typename ElemFromList<I, Indices, T...>::type& Get() {
    return static_cast<FlatTupleElemBase<FlatTuple, I>*>(this)->value;
  }
};
 
int main()
{
    using type = FlatTuple<bool, bool>;
    
    type val(true, true);
    (void)val;
}
В качестве ремонта, я заменяю фрагмент:
C++
1
using Indices = typename FlatTuple::FlatTupleBase::Indices;
На:
C++
1
2
  using Base = FlatTupleBase<FlatTuple<T...>, typename MakeIndexSequence<sizeof...(T)>::type>;
  using Indices = typename Base::Indices;
И сборка проходит успешно:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <iostream>
 
// Backport of std::index_sequence.
template <size_t... Is>
struct IndexSequence {
  using type = IndexSequence;
};
 
// Double the IndexSequence, and one if plus_one is true.
template <bool plus_one, typename T, size_t sizeofT>
struct DoubleSequence;
template <size_t... I, size_t sizeofT>
struct DoubleSequence<true, IndexSequence<I...>, sizeofT> {
  using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>;
};
template <size_t... I, size_t sizeofT>
struct DoubleSequence<false, IndexSequence<I...>, sizeofT> {
  using type = IndexSequence<I..., (sizeofT + I)...>;
};
 
// Backport of std::make_index_sequence.
// It uses O(ln(N)) instantiation depth.
template <size_t N>
struct MakeIndexSequence
    : DoubleSequence<N % 2 == 1, typename MakeIndexSequence<N / 2>::type,
                     N / 2>::type {};
 
template <>
struct MakeIndexSequence<0> : IndexSequence<> {};
 
// FIXME: This implementation of ElemFromList is O(1) in instantiation depth,
// but it is O(N^2) in total instantiations. Not sure if this is the best
// tradeoff, as it will make it somewhat slow to compile.
template <typename T, size_t, size_t>
struct ElemFromListImpl {};
 
template <typename T, size_t I>
struct ElemFromListImpl<T, I, I> {
  using type = T;
};
 
// Get the Nth element from T...
// It uses O(1) instantiation depth.
template <size_t N, typename I, typename... T>
struct ElemFromList;
 
template <size_t N, size_t... I, typename... T>
struct ElemFromList<N, IndexSequence<I...>, T...>
    : ElemFromListImpl<T, N, I>... {};
 
template <typename... T>
class FlatTuple;
 
template <typename Derived, size_t I>
struct FlatTupleElemBase;
 
template <typename... T, size_t I>
struct FlatTupleElemBase<FlatTuple<T...>, I> {
  using value_type =
      typename ElemFromList<I, typename MakeIndexSequence<sizeof...(T)>::type,
                            T...>::type;
  FlatTupleElemBase() = default;
  explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {}
  value_type value;
};
 
template <typename Derived, typename Idx>
struct FlatTupleBase;
 
template <size_t... Idx, typename... T>
struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
    : FlatTupleElemBase<FlatTuple<T...>, Idx>... {
  using Indices = IndexSequence<Idx...>;
  FlatTupleBase() = default;
  explicit FlatTupleBase(T... t)
      : FlatTupleElemBase<FlatTuple<T...>, Idx>(std::move(t))... {}
};
 
// Analog to std::tuple but with different tradeoffs.
// This class minimizes the template instantiation depth, thus allowing more
// elements that std::tuple would. std::tuple has been seen to require an
// instantiation depth of more than 10x the number of elements in some
// implementations.
// FlatTuple and ElemFromList are not recursive and have a fixed depth
// regardless of T...
// MakeIndexSequence, on the other hand, it is recursive but with an
// instantiation depth of O(ln(N)).
template <typename... T>
class FlatTuple: private FlatTupleBase<FlatTuple<T...>, typename MakeIndexSequence<sizeof...(T)>::type> 
{
  using Base = FlatTupleBase<FlatTuple<T...>, typename MakeIndexSequence<sizeof...(T)>::type>;
  using Indices = typename Base::Indices;
 
 public:
  FlatTuple() = default;
  explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {}
 
  template <size_t I>
  const typename ElemFromList<I, Indices, T...>::type& Get() const {
    return static_cast<const FlatTupleElemBase<FlatTuple, I>*>(this)->value;
  }
 
  template <size_t I>
  typename ElemFromList<I, Indices, T...>::type& Get() {
    return static_cast<FlatTupleElemBase<FlatTuple, I>*>(this)->value;
  }
};
 
int main()
{
    using type = FlatTuple<bool, bool>;
    
    type val(true, true);
    (void)val;
}



По хорошему, нужно проверить всю линейку: 2008/2010/2012/2013/2015/2017/2019
И на различных компиляторах gcc/clang/etc
К сожалению, у меня нет таких ресурсов
Будет классно, если форумчане скачают фреймворк с офф-сайта,
выполнят сборку и запустят тесты, что идут в комплекте с фреймворком.
И отпишут в тему о результатах.
Так мы можем помочь этому замечательному фреймворку.

В настоящий момент у gtest проблема с компиляцией.
проблема с компиляций собственных тестов.
проблема с прохождением этих тестов.

Вернуться к обсуждению:
Gtest, доступ к элементам базового класса-шаблона без указания параметров шаблона. баг или фича?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.05.2019, 20:39
Готовые ответы и решения:

Определение метода-шаблона за пределами шаблона класса
День добрый! Разбираюсь в шаблонах, решил копнуть поглубже. Вот пример: template &lt;typename T1&gt;...

Доступ к закрытым членам класса(шаблона)
Вопрос почему компилятор выдает ошибку в функции main? Ситуация следующая имеется шаблон (класс)...

Баг или фича
решил проверить на своем VS 2008 присвоение в сравнении написал char buf; char *buf1;...

Баг или фича ? =)
Thread threads = new Thread; for (int i = 0; i &lt; threads.Length; i++) {...

4
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.