Issue
I have a struct that is marked with the C++17's [[nodiscard]]
attribute. It is defined like this:
struct [[nodiscard]] MyObject final
{
explicit MyObject(int id);
~MyObject();
MyObject(const MyObject&) = delete;
MyObject& operator=(const MyObject&) = delete;
int id;
};
Now I want to export it from my dynamic library.
On MSVC, the syntax struct __declspec(dllexport) [[nodiscard]] MyObject final
works as expected.
But GCC fails to compile both struct __attribute__((dllexport)) [[nodiscard]] MyObject final
and struct [[nodiscard]] __attribute__((dllexport)) MyObject final
: the compiler just cannot handle such syntax.
And the syntax __attribute__((dllexport)) struct [[nodiscard]] MyObject final
compiles but doesn't seem to do what I want, because it produces the following warning:
:1:49: warning: attribute ignored in declaration of 'struct MyObject' [-Wattributes]
1 | __attribute__((dllexport)) struct [[nodiscard]] MyObject final | ^~~~~~~~
:1:49: note: attribute for 'struct MyObject' must follow the 'struct' keyword
So, how can I export a [[nodiscard]]
struct from a dynamic library on GCC?
Solution
All of this applies to both dllexport
and dllimport
.
This seems to be a bug in the GCC parser.
Clang manages to parse the struct __attribute__((dllexport)) [[nodiscard]] MyObject ...
version.
As was noted by @Artyer, GCC (and Clang) support the C++ syntax for dllexport
- [[gnu::dllexport]]
.
Also it should be noted that GCC on Windows (MinGW) supports __declspec(dllexport)
for compatibility with Visual C++ and actually parses class __declspec(dllexport) [[nodiscard]] Test ...
correctly (tested with GCC 8.1.0).
All of the above assumes you're compiling for Windows, where dllexport
actually means something. On other platforms the compiler will simply ignore it (and usually emit a warning).
On Linux one should use -fvisibility=hidden
to hide all symbols except the ones chosen by the attribute visibility("default")
. There is no "import" alternative - use "default"
both when building and using the library. When exporting a class on Linux, anything that you don't want to export can then be marked with visibility("hidden")
to override the class's attribute.
GCC and Clang support both syntaxes for visibility
: __attribute__((visibility("default")))
and [[gnu::visibility("default")]]
.
More on visibility in GCC can be found HERE.
I'm not sure how exporting symbols from shared libraries works on MacOS (maybe the same as on Linux?).
Answered By - andrey Answer Checked By - Timothy Miller (WPSolving Admin)