Có nhiều lý do tốt để thíchSố lượng mảng không sử dụng odr?
#include <cstdlib>
template<typename T, std::size_t N>
constexpr std::size_t ARRAY_COUNT_FUNC(T (&arr)[N]) { return N; }
hơn
#define ARRAY_COUNT_MACRO(arr) (sizeof(arr)/sizeof(*arr))
Một khác biệt quan trọng là khi một con trỏ (không phải là một mảng) được chuyển đến ARRAY_COUNT_MACRO
, nó âm thầm trả về một câu trả lời vô ích, nhưng chuyển cùng một đối số cho ARRAY_COUNT_FUNC
sẽ gây ra lỗi trình biên dịch chỉ ra lỗi.
Nhưng macro có một lợi thế: đối số của nó không được đánh giá.
#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);
Có cách tiếp cận nào khác có lợi ích của cả hai? I. e., Cái gì đó gây ra một lỗi biên dịch nếu đối số không phải là một mảng và không sử dụng đối số của nó.
Chúa chỉ biết được ý tưởng trước đây được ấp trứng bao lâu, nhưng [Microsoft sử dụng cơ bản cùng một thuật toán] (http://blogs.msdn.com/b/the1/archive/2004/05 /07/128242.aspx) cho macro '_countof (ar)' của chúng và ít nhất là '04 '. Cơ hội là họ có lẽ * không biết ơn * xé nó ra khỏi người khác. – WhozCraig