- edited description
C++17: Class template argument deduction fails with `upcxx::future`
CTAD doesn’t work with upcxx::future
, partly due to it being an alias
test2.cpp: In function ‘int main()’:
test2.cpp:21:48: error: class template argument deduction failed:
21 | upcxx::future fut = upcxx::make_future(4,3.14);
| ^
test2.cpp:21:48: error: call of overloaded ‘future1(upcxx::future<int, double>)’ is ambiguous
In file included from /home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend_fwd.hpp:24,
from /home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend.hpp:4,
from /home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/allocate.hpp:8,
from /home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/upcxx.hpp:5,
from test2.cpp:1:
/home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/fwd.hpp:76:12: note: candidate: ‘future1(upcxx::detail::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, T ...>)-> upcxx::detail::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, T ...> [with T = {int, double}]’
76 | struct future1;
| ^~~~~~~
In file included from /home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future.hpp:5,
from /home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/backend.hpp:5,
from /home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/allocate.hpp:8,
from /home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/upcxx.hpp:5,
from test2.cpp:1:
/home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/future1.hpp:105:5: note: candidate: ‘future1(const upcxx::detail::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, T ...>&)-> upcxx::detail::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, T ...> [with T = {int, double}]’
105 | future1(future1 const&) = default;
| ^~~~~~~
/home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/future1.hpp:107:5: note: candidate: ‘future1(const upcxx::detail::future1<Kind1, T ...>&)-> upcxx::detail::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, T ...> [with T = {int, double}; Kind1 = upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>]’
107 | future1(future1<Kind1,T...> const &that): impl_(that.impl_) {}
| ^~~~~~~
/home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/future1.hpp:109:5: note: candidate: ‘future1(upcxx::detail::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, T ...>&&)-> upcxx::detail::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, T ...> [with T = {int, double}]’
109 | future1(future1&&) = default;
| ^~~~~~~
/home/colin/work/upcxx/build/bld/upcxx.assert1.optlev0.dbgsym1.gasnet_seq.smp/include/upcxx/future/future1.hpp:111:5: note: candidate: ‘future1(upcxx::detail::future1<Kind1, T ...>&&)-> upcxx::detail::future1<upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>, T ...> [with T = {int, double}; Kind1 = upcxx::detail::future_kind_shref<upcxx::detail::future_header_ops_general>]’
111 | future1(future1<Kind1,T...> &&that):
| ^~~~~~~
Using upcxx::detail::future1
does deduce correctly.
The fix would either be to make upcxx::future
a class inheriting from future1
instead of an alias or to specify a deduction guide, although this would only work >=C++20 and not in C++17 due to alias deductions not being available, yet.
Here’s a reproducer:
#include <upcxx/upcxx.hpp>
int main()
{
upcxx::init();
upcxx::future fut = upcxx::make_future();
upcxx::finalize();
return 0;
}
Compiling this in C++17 gives an error about CTAD of aliases not being available until C++20 and building in C++20 mode gives an error like above.
Looking at the UPC++ spec, upcxx::future
is defined to be:
template<typename... T>
class future;
and not
template<typename... T>
using future = /* implementation defined */;
The distinction between a class and an alias matters, meaning our implementation of upcxx::future
is non-compliant with our specification. If we go with the simpler solution of an alias CTAD (C++20), we should update the spec to make upcxx::future
an alias. Otherwise CTAD would be expected to work in C++17 given the current spec.
Comments (3)
-
reporter -
- changed milestone to 2023.9.0 release
Mass roll-over of open issues to next release milestone
-
- removed milestone
Clear past Milestone for open issues
- Log in to comment
Added reproducer and investigation regarding the current UPC++ spec.