事后看来,我应该在发布之前尝试明显的。
Clang 将属性视为重复声明的附加属性,
[[nodiscard]] int libnamespace_dosomething(int, sometype*);
因此,在包含标头中的声明之前或之后编写 ^ 是有效的。
通过一些努力,可能可以将其包装在宏中以处理重复输入。我认为
#define NODISCARD(ARITY,X) /*careful*/
可以在 C++ 中实现,这样
NODISCARD(2, libnamespace_dosomething);
扩展为与传递的函数匹配但添加了 nodiscard 的声明。对从函数指针推断出数量没有信心。如果我破解上述内容,我会更新这个答案。
上述建议的示例
#include <tuple>
namespace nodiscard {
// Extract return / argument types from address of function symbol
template <typename F> struct trait;
template <typename R, typename... Ts> struct trait<R (*)(Ts...)> {
constexpr static const size_t nargs = sizeof...(Ts);
typedef R ReturnType;
template <size_t i> struct arg {
typedef typename std::tuple_element<i, std::tuple<Ts...>>::type type;
};
};
} // namespace nodiscard
#define NODISCARD_INSTANTIATE(SYM, ARITY) \
static_assert(ARITY == nodiscard::trait<decltype(&SYM)>::nargs, \
"Arity Error"); \
NODISCARD_INSTANTIATE_##ARITY(SYM, nodiscard::trait<decltype(&SYM)>)
#define NODISCARD_INSTANTIATE_0(SYM, T) [[nodiscard]] T::ReturnType SYM();
#define NODISCARD_INSTANTIATE_1(SYM, T) \
[[nodiscard]] T::ReturnType SYM(typename T::template arg<0>::type);
#define NODISCARD_INSTANTIATE_2(SYM, T) \
[[nodiscard]] T::ReturnType SYM(typename T::template arg<0>::type, \
typename T::template arg<1>::type);
#define NODISCARD_INSTANTIATE_3(SYM, T) \
[[nodiscard]] T::ReturnType SYM(typename T::template arg<0>::type, \
typename T::template arg<1>::type, \
typename T::template arg<2>::type);
// had to go up to 8, copy&paste style