boost-ext/te

Compilation of Test fails on gcc 8.2

furkanusta opened this issue · 2 comments

Hi, I am using g++ (GCC) 8.2.1 20181011 (Red Hat 8.2.1-4) on Fedora 28
I've tried to compile the library with default parameters on CMake and got the following error.
(I couldn't make the output prettier sorry about that)

include/boost/te.hpp: In instantiation of ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&, std::index_sequence<Ns ...>) [with T = Circle; T_ = Circle; long unsigned int ...Ns = {}; I = DrawableT<std::__cxx11::basic_stringstream >; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable; std::index_sequence<Ns ...> = std::integer_sequence]’:

include/boost/te.hpp:223:68: required from ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&, TRequires) [with T = Circle; TRequires = boost::te::v1::detail::type_list; I = DrawableT<std::__cxx11::basic_stringstream >; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable]’

include/boost/te.hpp:213:74: required from ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&) [with T = Circle; = void; I = DrawableT<std::__cxx11::basic_stringstream >; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable]’

test.cpp:29:61: required from here
include/boost/te.hpp:231:33: error: static assertion failed
static_assert(sizeof...(Ns) > 0);
~~~~~~~~~~~~~~^~~

I've tried to make a minimal test case on godbolt but instead I got this: https://godbolt.org/z/bbxlXl which also fails on 8.2 (fine on 7.x) but gives a slightly different error message.

Since it compiles fine on both gcc 7.x and clang-trunk, I am not sure whether the problem is with the library or either of the compilers

Confirmed.

gcc 8.3.0 fails on these lines, giving similar error output to that in the original post:

test should_support_templated_interfaces = [] {
...
line 356:     te::poly<DrawableT<std::ostream>> drawable{Square{}};
...
line 363:     te::poly<DrawableT<std::stringstream>> drawable{Circle{}};
...
}
...
test should_support_function_lambda_expr = [] {
...
line 411:    te::poly<Function<int(int)>> f{[](int i) { return i; }};
...
line 417:     te::poly<Function<int(int, int)>> f{[](int a, int b) { return a + b; }};
...

gcc 9.0.1 (not yet released, from git commit 6977c762 on 2019-04-25) has the same problem on the same lines, with the following output. Notably, it still only has these problems, not picking up the extra ones way below from clang 8.0.0.

include/boost/te.hpp: In instantiation of ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&, std::index_sequence<Ns ...>) [with T = Squa
re; T_ = Square; long unsigned int ...Ns = {}; I = DrawableT<std::basic_ostream<char> >; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable; std::
index_sequence<Ns ...> = std::integer_sequence<long unsigned int>]’:
include/boost/te.hpp:223:68:   required from ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&, TRequires) [with T = Square; TRequires $
 boost::te::v1::detail::type_list<void>; I = DrawableT<std::basic_ostream<char> >; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable]’
include/boost/te.hpp:213:74:   required from ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&) [with T = Square; <template-parameter-2-
2> = void; I = DrawableT<std::basic_ostream<char> >; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable]’
test/te.cpp:356:56:   required from here
include/boost/te.hpp:231:33: error: static assertion failed
  231 |     static_assert(sizeof...(Ns) > 0);
      |                   ~~~~~~~~~~~~~~^~~
include/boost/te.hpp: In instantiation of ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&, std::index_sequence<Ns ...>) [with T = Circ
le; T_ = Circle; long unsigned int ...Ns = {}; I = DrawableT<std::__cxx11::basic_stringstream<char> >; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static
_vtable; std::index_sequence<Ns ...> = std::integer_sequence<long unsigned int>]’:
include/boost/te.hpp:223:68:   required from ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&, TRequires) [with T = Circle; TRequires =
 boost::te::v1::detail::type_list<void>; I = DrawableT<std::__cxx11::basic_stringstream<char> >; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtabl
e]’
include/boost/te.hpp:213:74:   required from ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&) [with T = Circle; <template-parameter-2-
2> = void; I = DrawableT<std::__cxx11::basic_stringstream<char> >; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable]’
test/te.cpp:363:61:   required from here
include/boost/te.hpp:231:33: error: static assertion failed
include/boost/te.hpp: In instantiation of ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&, std::index_sequence<Ns ...>) [with T = <lam
bda()>::<lambda(int)>; T_ = <lambda()>::<lambda(int)>; long unsigned int ...Ns = {}; I = Function<int(int)>; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::
static_vtable; std::index_sequence<Ns ...> = std::integer_sequence<long unsigned int>]’:
include/boost/te.hpp:223:68:   required from ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&, TRequires) [with T = <lambda()>::<lambda
(int)>; TRequires = boost::te::v1::detail::type_list<void>; I = Function<int(int)>; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable]’
include/boost/te.hpp:213:74:   required from ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&) [with T = <lambda()>::<lambda(int)>; <te
mplate-parameter-2-2> = void; I = Function<int(int)>; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable]’
test/te.cpp:411:59:   required from here
include/boost/te.hpp:231:33: error: static assertion failed
include/boost/te.hpp: In instantiation of ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&, std::index_sequence<Ns ...>) [with T = <lam
bda()>::<lambda(int, int)>; T_ = <lambda()>::<lambda(int, int)>; long unsigned int ...Ns = {}; I = Function<int(int, int)>; TStorage = boost::te::v1::dynamic_storage; TVtable =
boost::te::v1::static_vtable; std::index_sequence<Ns ...> = std::integer_sequence<long unsigned int>]’:
include/boost/te.hpp:223:68:   required from ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&, TRequires) [with T = <lambda()>::<lambda
(int, int)>; TRequires = boost::te::v1::detail::type_list<void>; I = Function<int(int, int)>; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable]’
include/boost/te.hpp:213:74:   required from ‘constexpr boost::te::v1::poly<I, TStorage, TVtable>::poly(T&&) [with T = <lambda()>::<lambda(int, int)>
; <template-parameter-2-2> = void; I = Function<int(int, int)>; TStorage = boost::te::v1::dynamic_storage; TVtable = boost::te::v1::static_vtable]’
test/te.cpp:417:75:   required from here
include/boost/te.hpp:231:33: error: static assertion failed
make[2]: *** [test/CMakeFiles/te.dir/build.make:63: test/CMakeFiles/te.dir/te.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:646: test/CMakeFiles/te.dir/all] Error 2
make: *** [Makefile:95: all] Error 2

clang 8.0.0 fails with this output:

In file included from example/unified.cpp:11:
include/boost/te.hpp:231:5: error: static_assert failed due to requirement 'sizeof...(Ns) > 0'
    static_assert(sizeof...(Ns) > 0);
    ^             ~~~~~~~~~~~~~~~~~
include/boost/te.hpp:222:9: note: in instantiation of function template specialization 'boost::te::v1::poly<Drawable, boost::te::v1::dynamic_storage,
      boost::te::v1::static_vtable>::poly<Circle, Circle>' requested here
      : poly{std::forward<T>(t),
        ^
include/boost/te.hpp:212:9: note: in instantiation of function template specialization 'boost::te::v1::poly<Drawable, boost::te::v1::dynamic_storage,
      boost::te::v1::static_vtable>::poly<Circle, boost::te::v1::detail::type_list<void> >' requested here
      : poly{std::forward<T>(t),
        ^
example/unified.cpp:47:8: note: in instantiation of function template specialization 'boost::te::v1::poly<Drawable, boost::te::v1::dynamic_storage,
      boost::te::v1::static_vtable>::poly<Circle, void>' requested here
  draw(Circle{});  // prints Non-member Circle
       ^
In file included from example/unified.cpp:11:
include/boost/te.hpp:231:5: error: static_assert failed due to requirement 'sizeof...(Ns) > 0'
    static_assert(sizeof...(Ns) > 0);
    ^             ~~~~~~~~~~~~~~~~~
include/boost/te.hpp:222:9: note: in instantiation of function template specialization 'boost::te::v1::poly<Drawable, boost::te::v1::dynamic_storage,
      boost::te::v1::static_vtable>::poly<Square, Square>' requested here
      : poly{std::forward<T>(t),
        ^
include/boost/te.hpp:212:9: note: in instantiation of function template specialization 'boost::te::v1::poly<Drawable, boost::te::v1::dynamic_storage,
      boost::te::v1::static_vtable>::poly<Square, boost::te::v1::detail::type_list<void> >' requested here
      : poly{std::forward<T>(t),
        ^
example/unified.cpp:48:8: note: in instantiation of function template specialization 'boost::te::v1::poly<Drawable, boost::te::v1::dynamic_storage,
      boost::te::v1::static_vtable>::poly<Square, void>' requested here
  draw(Square{});  // prints Member Square
       ^

Commenting out lines 47-48 in example/unified.cpp proceeds, only to run into similar warnings from:

  • example/nonowning.cpp lines 38-39
  • example/storage.cpp lines 33-34
  • example/overload.cpp line 33
  • example/combined.cpp lines 33-34
  • example/override.cpp lines 63-64, 66-67, 69, 71
  • example/macro.cpp line 26
  • example/forward.cpp lines 36-37
  • example/drawable.cpp lines 31-32
  • example/function.cpp line 34
  • test/te.cpp lines 275, 323-324, 330-331, 337-338

Then this type of warning in these places, which seems odd to me because include/boost/te.hpp has #pragma once, on:

  • example/overload.cpp, as shown below
  • example/override.cpp
  • example/macro.cpp
  • example/container.cpp
In file included from example/overload.cpp:10:
include/boost/te.hpp:33:17: error: redefinition of 'get'
    friend auto get(mappings) { return T{}; }
                ^
include/boost/te.hpp:256:8: note: in instantiation of template class 'boost::te::v1::detail::mappings<Addable,
      1>::set<boost::te::v1::detail::type_list<Addable::(lambda at example/overload.cpp:21:36), int &, int &> >' requested here
  void(typename mappings<I, N>::template set<type_list<TExpr, Ts...> >{});
       ^
include/boost/te.hpp:281:18: note: in instantiation of function template specialization 'boost::te::v1::detail::call_impl<Addable, 1, int,
      Addable::(lambda at example/overload.cpp:21:36), int &, int &>' requested here
  return detail::call_impl<I>(
                 ^
example/overload.cpp:17:16: note: in instantiation of function template specialization 'boost::te::v1::call<int, 0, Addable::(lambda at
      example/overload.cpp:21:36), Addable, int &, int &>' requested here
    return te::call<int>(add_impl, *this, a, b);
               ^
include/boost/te.hpp:33:17: note: previous definition is here
    friend auto get(mappings) { return T{}; }
                ^

I'm not 100% certain, but it seems to me that this is using the so-called C++ Type Loophole.

Maybe clang and gcc have dropped support for it given that CWG wants to make it ill-formed in the future?

This may point to a possible lead for how to make the code work without relying on that loophole