No, there is no portable way of doing that. Then again, there are no portable ways to use #pragma at all. Because of this, many C/C++ compilers define their own methods for doing pragma-like things, and they often can be embedded in macros, but you need a different macro definition on every compiler. If you are willing to go that route, you often end up doing stuff like this:
#if defined(COMPILER_GCC)
#define Weak_b
#define Weak_e __attribute__((weak))
#elif defined(COMPILER_FOO)
#define Weak_b __Is_Weak
#define Weak_e
#endif
#define DEFINE_DELETE_OBJECT(type) \
Weak_b void delete_ ## type_(int handle) Weak_e; \
Weak_b void delete_ ## type(int handle) Weak_e;
In case its not obvious you want to define Weak_b
and Weak_e
as begin-and-end bracketing constructs because some compilers like GCC add the attributes as an addendum to a type signature, and some, like MSC add it as a prefix (or at least it did once, its been years since I've used MSC). Having bracketing contructs allows you to define something that always works, even if you have to pass the entire type signature into a compiler construct.
Of course, if you try porting this to a compiler without the attributes you want, there's nothing you can do but leave the macros expand to nothing and hope your code still runs. In case of purely warning or optimizing pragmas, this is likely. In other cases, not so much.
Oh, and I suspect you'd actually need to define Weak_b and Weak_e as macros that take parameters, but I wasn't willing to read through the docs for how to create a weak definition just for this example. I leave that as an exercise for the reader.