Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

has_duplicates() doesn't build in CPP11 mode #1008

Open
dkogan opened this issue Jan 2, 2025 · 0 comments
Open

has_duplicates() doesn't build in CPP11 mode #1008

dkogan opened this issue Jan 2, 2025 · 0 comments

Comments

@dkogan
Copy link

dkogan commented Jan 2, 2025

Hi. New code was added in 20.39 that doesn't build, as opposed to 20.37. I discovered this as I was updating the Debian package. It produces errors like this:

$ g++ \
   -DETL_DEBUG \
   -I../../test/../include \
   -isystem ../../test/UnitTest++/.. \
   -Wno-aggressive-loop-optimizations \
   -Wno-pessimizing-move \
   -std=gnu++20 \
   -fno-omit-frame-pointer \
   -fno-common \
   -Wall \
   -Wextra \
   -Werror \
   -Wfloat-equal \
   -Wuseless-cast \
   -Wshadow \
   -Wnull-dereference \
   -o /tmp/tst.o \
   -c ../../test/test_observer.cpp


In file included from ../../test/../include/etl/algorithm.h:42,
                 from ../../test/../include/etl/observer.h:54,
                 from ../../test/test_observer.cpp:31:
../../test/../include/etl/type_traits.h: In instantiation of ‘struct etl::has_duplicates<const {anonymous}::Notification3&>’:
../../test/../include/etl/type_traits.h:2310:10:   required from ‘struct etl::has_duplicates<{anonymous}::Notification2&, const {anonymous}::Notification3&>’
 2310 |   struct has_duplicates<TFirst, TRest...> : etl::conditional_t<etl::is_one_of<TFirst, TRest...>::value,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../test/../include/etl/observer.h:308:5:   required from ‘class etl::observer<{anonymous}::Notification2&, const {anonymous}::Notification3&>’
  308 |     ETL_STATIC_ASSERT((!etl::has_duplicates<T1, TRest...>::value), "Observer has duplicate notification types");
      |                                                            ^~~~~
../../test/../include/etl/observer.h:304:9:   required from ‘class etl::observer<{anonymous}::Notification1, {anonymous}::Notification2&, const {anonymous}::Notification3&>’
  304 |   class observer<T1, TRest...> : public observer<T1>, public observer<TRest...>
      |         ^~~~~~~~~~~~~~~~~~~~~~
../../test/test_observer.cpp:147:26:   required from here
  147 | class Observer1 : public ObserverType
      |                          ^~~~~~~~~~~~
../../test/../include/etl/type_traits.h:2310:98: error: wrong number of template arguments (1, should be at least 2)
 2310 |   struct has_duplicates<TFirst, TRest...> : etl::conditional_t<etl::is_one_of<TFirst, TRest...>::value,
      |                                                                                                  ^~~~~
../../test/../include/etl/type_traits.h:1355:10: note: provided for ‘template<class T, class T1, class ... TRest> struct etl::is_one_of’
 1355 |   struct is_one_of
      |          ^~~~~~~~~


In file included from ../../test/../include/etl/type_traits.h:58:
../../test/../include/etl/observer.h: In instantiation of ‘class etl::observer<{anonymous}::Notification2&, const {anonymous}::Notification3&>’:
../../test/../include/etl/observer.h:304:9:   required from ‘class etl::observer<{anonymous}::Notification1, {anonymous}::Notification2&, const {anonymous}::Notification3&>’
  304 |   class observer<T1, TRest...> : public observer<T1>, public observer<TRest...>
      |         ^~~~~~~~~~~~~~~~~~~~~~
../../test/test_observer.cpp:147:26:   required from here
  147 | class Observer1 : public ObserverType
      |                          ^~~~~~~~~~~~
../../test/../include/etl/observer.h:308:60: error: ‘value’ is not a member of ‘etl::has_duplicates<{anonymous}::Notification2&, const {anonymous}::Notification3&>’
  308 |     ETL_STATIC_ASSERT((!etl::has_duplicates<T1, TRest...>::value), "Observer has duplicate notification types");
      |                                                            ^~~~~
../../test/../include/etl/static_assert.h:35:63: note: in definition of macro ‘ETL_STATIC_ASSERT’
   35 |   #define ETL_STATIC_ASSERT(Condition, Message) static_assert(Condition, Message)
      |                                                               ^~~~~~~~~
../../test/../include/etl/observer.h: In instantiation of ‘class etl::observer<{anonymous}::Notification1, {anonymous}::Notification2&, const {anonymous}::Notification3&>’:
../../test/test_observer.cpp:147:26:   required from here
  147 | class Observer1 : public ObserverType
      |                          ^~~~~~~~~~~~
../../test/../include/etl/observer.h:308:60: error: ‘value’ is not a member of ‘etl::has_duplicates<{anonymous}::Notification1, {anonymous}::Notification2&, const {anonymous}::Notification3&>’
  308 |     ETL_STATIC_ASSERT((!etl::has_duplicates<T1, TRest...>::value), "Observer has duplicate notification types");
      |                                                            ^~~~~
../../test/../include/etl/static_assert.h:35:63: note: in definition of macro ‘ETL_STATIC_ASSERT’
   35 |   #define ETL_STATIC_ASSERT(Condition, Message) static_assert(Condition, Message)
      |                                                               ^~~~~~~~~
../../test/../include/etl/type_traits.h: In instantiation of ‘struct etl::has_duplicates<int>’:
../../test/../include/etl/type_traits.h:2310:10:   required from ‘struct etl::has_duplicates<void, int>’
 2310 |   struct has_duplicates<TFirst, TRest...> : etl::conditional_t<etl::is_one_of<TFirst, TRest...>::value,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../test/../include/etl/observer.h:308:5:   required from ‘class etl::observer<void, int>’
  308 |     ETL_STATIC_ASSERT((!etl::has_duplicates<T1, TRest...>::value), "Observer has duplicate notification types");
      |                                                            ^~~~~
../../test/test_observer.cpp:237:32:   required from here
  237 | class ObserverVoidInt : public ObserverVoidIntType
      |                                ^~~~~~~~~~~~~~~~~~~
../../test/../include/etl/type_traits.h:2310:98: error: wrong number of template arguments (1, should be at least 2)
 2310 |   struct has_duplicates<TFirst, TRest...> : etl::conditional_t<etl::is_one_of<TFirst, TRest...>::value,
      |                                                                                                  ^~~~~
../../test/../include/etl/type_traits.h:1355:10: note: provided for ‘template<class T, class T1, class ... TRest> struct etl::is_one_of’
 1355 |   struct is_one_of
      |          ^~~~~~~~~
../../test/../include/etl/observer.h: In instantiation of ‘class etl::observer<void, int>’:
../../test/test_observer.cpp:237:32:   required from here
  237 | class ObserverVoidInt : public ObserverVoidIntType
      |                                ^~~~~~~~~~~~~~~~~~~
../../test/../include/etl/observer.h:308:60: error: ‘value’ is not a member of ‘etl::has_duplicates<void, int>’
  308 |     ETL_STATIC_ASSERT((!etl::has_duplicates<T1, TRest...>::value), "Observer has duplicate notification types");
      |                                                            ^~~~~
../../test/../include/etl/static_assert.h:35:63: note: in definition of macro ‘ETL_STATIC_ASSERT’
   35 |   #define ETL_STATIC_ASSERT(Condition, Message) static_assert(Condition, Message)
      |                                                               ^~~~~~~~~

has_duplicates() is intended to take any number of templated types, and recursively wittles them down one by one. The problem is that the CPP11 path has matching calls for 0 arguments and >=2 arguments, but not for ` argument. A patch to add that path:

diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h
index f086b84..8833a2a 100644
--- a/include/etl/generators/type_traits_generator.h
+++ b/include/etl/generators/type_traits_generator.h
@@ -2314,13 +2314,14 @@ typedef integral_constant<bool, true>  true_type;
   struct has_duplicates;
 
   template <typename TFirst, typename... TRest>
   struct has_duplicates<TFirst, TRest...> : etl::conditional_t<etl::is_one_of<TFirst, TRest...>::value,
                                                                etl::true_type,
                                                                has_duplicates<TRest...>> {};
-
+  template <typename TFirst>
+  struct has_duplicates<TFirst> : etl::false_type {};
   template <>
   struct has_duplicates<> : etl::false_type {};
 #endif
 
 #if ETL_USING_CPP17
   template <typename... TTypes>

I'm building the new Debian package with this patch. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant