c++ - 不使用 odr 的数组计数?

标签 c++

有几个很好的理由去选择

#include <cstdlib>

template<typename T, std::size_t N>
constexpr std::size_t ARRAY_COUNT_FUNC(T (&arr)[N]) { return N; }

而不是

#define ARRAY_COUNT_MACRO(arr) (sizeof(arr)/sizeof(*arr))

一个重要的区别是,当一个指针(不是数组)被传递给 ARRAY_COUNT_MACRO 时,它会默默地返回一个无用的答案,但是将相同的参数传递给 ARRAY_COUNT_FUNC 会导致编译错误指出错误。

但是宏确实有一个优点:它的参数是未计算的。

#include <utility>
struct S {
    int member_array[5];
};

// OK:
std::size_t count1 = ARRAY_COUNT_MACRO(std::declval<S&>().member_array);

// ERROR: std::declval is odr-used!
std::size_t count2 = ARRAY_COUNT_FUNC(std::declval<S&>().member_array);

是否有另一种方法可以同时发挥两者的优势?即,如果参数不是数组,并且不 odr-use 其参数,则会导致编译错误。

最佳答案

无耻地从 Chromium 项目中敲诈,如所述 here .

#include <utility>
#include <cstdlib>

template<typename T, std::size_t N>
constexpr std::size_t ARRAY_COUNT_FUNC(T (&arr)[N]) { return N; }

#define ARRAY_COUNT_MACRO(arr) (sizeof(arr)/sizeof(*arr))

// Template for typesafey goodness.
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
// sizeof to avoid actually calling the function.
#define arraysize(array) (sizeof(ArraySizeHelper(array)))

struct S {
    int member_array[5];
};

int main()
{

    // OK:
    std::size_t count1 = ARRAY_COUNT_MACRO(std::declval<S&>().member_array);

    // ERROR: std::declval is odr-used!
    //std::size_t count2 = ARRAY_COUNT_FUNC(std::declval<S&>().member_array);

    // OK:
    std::size_t count2 = arraysize(std::declval<S&>().member_array);

    // ERROR:
    // int * p;
    // std::size_t count3 = arraysize(p);
}

关于c++ - 不使用 odr 的数组计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14713068/

相关文章:

c++ - qt中QGraphicsScene中的绘画

c++ - constexpr 的运行时错误

c++ - 是否 sizeof(T) == sizeof(const T) 和 alignof(T) == alignof(const T)

c++ - 带有似乎未被 ODR 使用的静态常量的链接器错误

c++ - 获取复选框的大小

c++ - 基于策略的设计——策略实现必须访问主机类的成员

c++ - 尾随返回类型、decltype 和 const-ness

C++ 作用域错误

c++ - 我可以停止 GCC 将标准库名称包含到全局 namespace 中吗?

c++ - 当依赖库之一无法编译时,如何防止 Visual Studio 构建我的整个解决方案?