-
Notifications
You must be signed in to change notification settings - Fork 73
Description
In our code, I stumbled upon a problem, where we couldn't include the sycl/sylc.hpp header in a public API header.
A simple example showing the problem:
foo.hpp
#include "sycl/sycl.hpp"
void foo(const sycl::queue& q);foo.cpp
#include "foo.hpp"
void foo(const sycl::queue& q) {
// do something with the sycl::queue
q.get_device().template get_info<sycl::info::device::name>();
}This example has one major drawback: the sycl/sycl.hpp header has to be included in a public API header, leaking all of its implementation to said public API.
The easiest way to prevent this is to forward declare the sycl::queue:
foo.hpp
namespace sycl {
class queue;
}
void foo(const sycl::queue& q);However, this is currently not possible (at least for DPC++ and hipSYCL).
DPC++ for example throws the following compiler error:
> clang++ -fsycl -fsycl-targets=nvptx64-nvidia-cuda -Xsycl-target-backend=nvptx64-nvidia-cuda --offload-arch=sm_86 foo.cpp main.cpp
In file included from foo.cpp:3:
In file included from /intel_llvm/build/install/include/sycl/sycl.hpp:16:
In file included from /intel_llvm/build/install/include/sycl/backend.hpp:18:
In file included from /intel_llvm/build/install/include/sycl/detail/backend_traits_opencl.hpp:26:
/intel_llvm/build/install/include/sycl/queue.hpp:1544:31: error: reference to 'queue' is ambiguous
template <> struct hash<sycl::queue> {
^
./foo.hpp:2:9: note: candidate found by name lookup is 'sycl::queue'
class queue;
^
/intel_llvm/build/install/include/sycl/queue.hpp:88:21: note: candidate found by name lookup is 'sycl::_V1::queue'
class __SYCL_EXPORT queue : public detail::OwnerLessBase<queue> {
^
/intel_llvm/build/install/include/sycl/queue.hpp:1545:33: error: reference to 'queue' is ambiguous
size_t operator()(const sycl::queue &Q) const {
^
./foo.hpp:2:9: note: candidate found by name lookup is 'sycl::queue'
class queue;
^
/intel_llvm/build/install/include/sycl/queue.hpp:88:21: note: candidate found by name lookup is 'sycl::_V1::queue'
class __SYCL_EXPORT queue : public detail::OwnerLessBase<queue> {
^
/intel_llvm/build/install/include/sycl/queue.hpp:1547:9: error: no matching function for call to 'getSyclObjImpl'
sycl::detail::getSyclObjImpl(Q));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/intel_llvm/build/install/include/sycl/detail/common.hpp:240:42: note: candidate template ignored: substitution failure [with Obj = sycl::queue]: incomplete type 'sycl::queue' named in nested name specifier
template <class Obj> decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject) {
~~~ ^
foo.cpp:7:22: error: reference to 'queue' is ambiguous
void foo(const sycl::queue& q) {
^
./foo.hpp:2:9: note: candidate found by name lookup is 'sycl::queue'
class queue;
^
/intel_llvm/build/install/include/sycl/properties/queue_properties.hpp:67:7: note: candidate found by name lookup is 'sycl::_V1::queue'
class queue;
^
foo.cpp:8:17: error: member access into incomplete type 'const sycl::queue'
std::cout << q.get_device().template get_info<sycl::info::device::name>() << std::endl;
^
./foo.hpp:2:9: note: forward declaration of 'sycl::queue'
class queue;
^
5 errors generated.
For hipSYCL the error looks as follows:
syclcc --hipsycl-targets="cuda:sm_86" foo.cpp main.cpp
syclcc warning: No optimization flag was given, optimizations are disabled by default. Performance may be degraded. Compile with e.g. -O2/-O3 to enable optimizations.
foo.cpp:8:17: error: member access into incomplete type 'const sycl::queue'
std::cout << q.get_device().template get_info<sycl::info::device::name>() << std::endl;
^
./foo.hpp:2:9: note: forward declaration of 'sycl::queue'
class queue;
^
1 error generated when compiling for sm_86.
Therefore, it would be nice to standardize a new header, e.g., called sycl/syclfwd.hpp (like the C++ standard library header iosfwd) which forward declares all possible classes. After a short look into the standard (note: most likely incomplete) that should be possible for the following classes:
sycl/syclfwd.hpp
namespace sycl {
class platform;
class context;
class device;
class queue;
class event;
// ...
}Advantages:
- reduce header dependencies
- possible improve compile times in some scenarios
- it should not break any existing code since it adds a new header with simple forward declarations
Disadvantages:
- have to maintain an additional header
- the forward declared classes may never become template classes