0

我正在使用一个我无法编辑且不想分叉的库,它有一堆 int 错误返回样式的函数:

int libnamespace_dosomething(int, sometype*);

我希望该库具有[[nodiscard]]__attribute__((warn_unused_result))在大多数(可能是所有)接口上,以便当我无法检查调用是否成功时编译器会发出声音。

关于如何实现这一目标的任何建议?

目前的想法是相当劳动密集型的:

  • 编辑标题,修复错误,将标题放回原处。偶尔重复
  • 基于宏的丑陋的东西,也许能够从nm | bash
  • 铿锵插件

编辑:我正在考虑的包装方法是

int libcall(float);
#define libcall(...) mylibcall(__VA_ARGS__)
[[nodiscard]] inline int mylibcall(float x)
{
  return (libcall)(x);
}
4

1 回答 1

0

事后看来,我应该在发布之前尝试明显的。

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
于 2021-05-20T18:00:04.637 回答