Não, não existe uma maneira portátil de fazer isso. Então, novamente, não há nenhuma maneira portátil de usar #pragma. Por causa disso, muitos compiladores C / C ++ definem seus próprios métodos para fazer coisas do tipo pragma, e eles geralmente podem ser embutidos em macros, mas você precisa de uma definição de macro diferente em cada compilador. Se você está disposto a seguir esse caminho, geralmente acaba fazendo coisas como estas:
#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;
Caso não seja óbvio que você deseja definir Weak_b
e Weak_e
como construções de colchetes de início e fim, porque alguns compiladores como o GCC adicionam os atributos como um adendo a uma assinatura de tipo, e alguns, como o MSC, adicionam-no como um prefixo (ou pelo menos o fizeram uma vez, já faz anos que não uso o MSC). Ter contruções de colchetes permite que você defina algo que sempre funciona, mesmo se você tiver que passar a assinatura de tipo inteira para uma construção de compilador.
Claro, se você tentar portar isso para um compilador sem os atributos desejados, não há nada que você possa fazer a não ser deixar as macros se expandirem e esperar que seu código ainda seja executado. No caso de meramente advertir ou otimizar pragmas, isso é provável. Em outros casos, nem tanto.
Ah, e eu suspeito que você realmente precisa definir Weak_b e Weak_e como macros que usam parâmetros, mas eu não estava disposto a ler a documentação para saber como criar uma definição fraca apenas para este exemplo. Deixo isso como um exercício para o leitor.