C++ odr不使用的数组计数?

C++ odr不使用的数组计数?,c++,C++,有几个很好的理由选择 #include <cstdlib> template<typename T, std::size_t N> constexpr std::size_t ARRAY_COUNT_FUNC(T (&arr)[N]) { return N; } 一个重要的区别是,当指针(不是数组)被传递到array\u COUNT\u MACRO时,它会默默地返回一个没有帮助的答案,但将相同的参数传递到array\u COUNT\u FUNC会导致编译器错误

有几个很好的理由选择

#include <cstdlib>

template<typename T, std::size_t N>
constexpr std::size_t ARRAY_COUNT_FUNC(T (&arr)[N]) { return N; }
一个重要的区别是,当指针(不是数组)被传递到
array\u COUNT\u MACRO
时,它会默默地返回一个没有帮助的答案,但将相同的参数传递到
array\u COUNT\u 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);
#包括
结构{
int成员_数组[5];
};
//好:
std::size\u t count1=ARRAY\u COUNT\u宏(std::declval().member\u数组);
//错误:std::declval正在使用odr!
std::size\u t count2=ARRAY\u COUNT\u FUNC(std::declval().member\u ARRAY);

是否有另一种兼顾两者优点的方法?例如,如果参数不是数组,并且odr不使用其参数,则会导致编译错误。

如前所述,无耻地从Chromium项目中剽窃

#包括
#包括
模板
constexpr std::size\u t ARRAY\u COUNT\u FUNC(t(&arr)[N]){return N;}
#定义数组计数宏(arr)(sizeof(arr)/sizeof(*arr))
//typesafey的模板。
模板
char(&ArraySizeHelper(T(&array)[N]))[N];
//sizeof以避免实际调用该函数。
#定义arraysize(数组)(sizeof(ArraySizeHelper(数组)))
结构{
int成员_数组[5];
};
int main()
{
//好:
std::size\u t count1=ARRAY\u COUNT\u宏(std::declval().member\u数组);
//错误:std::declval正在使用odr!
//std::size\u t count2=ARRAY\u COUNT\u FUNC(std::declval().member\u ARRAY);
//好:
std::size\u t count2=arraysize(std::declval().member\u数组);
//错误:
//int*p;
//std::size\u t count3=数组化(p);
}

。。。然后我记得
有一个
std::is\u数组
模板。另一个解决方案:

#include <type_traits>

template<typename T>
constexpr auto ArrayCountImpl(std::nullptr_t)
    -> typename std::enable_if<std::is_array<typename
                                   std::remove_reference<T>::type>::value,
                               std::size_t>::type
{ return std::extent<typename std::remove_reference<T>::type>::value; }

template<typename T>
std::size_t ArrayCountImpl(...)
{ static_assert(!std::is_same<T,T>::value,
                "Argument type is not an array"); }

#define ARRAY_COUNT_MACRO_2(arr) (ArrayCountImpl<decltype(arr)>(nullptr))
#包括
模板
constexpr auto ArrayCountImpl(std::nullptr\t)
->typename std::enable_if::type
{return std::extent::value;}
模板
标准::大小\u t数组计数(…)
{static_assert(!std::is_same::value,
“参数类型不是数组”);}
#定义数组计数宏2(arr)(ArrayCountImpl(nullptr))

上帝只知道这个想法是在多长时间前第一次酝酿出来的,但对于他们的
\u countof(ar)
宏来说,至少从2004年开始。很有可能他们会毫不犹豫地从其他人那里剽窃。
#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);
}
#include <type_traits>

template<typename T>
constexpr auto ArrayCountImpl(std::nullptr_t)
    -> typename std::enable_if<std::is_array<typename
                                   std::remove_reference<T>::type>::value,
                               std::size_t>::type
{ return std::extent<typename std::remove_reference<T>::type>::value; }

template<typename T>
std::size_t ArrayCountImpl(...)
{ static_assert(!std::is_same<T,T>::value,
                "Argument type is not an array"); }

#define ARRAY_COUNT_MACRO_2(arr) (ArrayCountImpl<decltype(arr)>(nullptr))