2
using my_array = std::array<char, 16384>;
void compare(const my_array* a) {
    //...
    char b[20000];
    //...
    static_assert(a->size() < sizeof(b)/sizeof(b[0]), "text"); //<compile time error: static_assert expression is not an integral constant expression
    strlcpy(b, a->data(), a->size());
    //...
}

my_array A;
compare(&A); 

Size of all objects of type my_array is known at compile time.

Unfortunately its not reasonable to copy them by value to each function, which is going to use it. Reference is forbidden here also, because it may allocate a pointer, which here is the problem.

But I would like to have a compile time checks as in the example above, because logically I don't see a reason, why I can't: the type is known, the size is defined.

This variant doesn't work: static_assert(my_array::size() < 20000, "text");, obviously, because std::array<...>::size() is not static.

How can I do this check?

Arkady
  • 2,084
  • 3
  • 27
  • 48
  • Did you simply try using elementary specialization to pull out `my_array`'s 2nd template parameter? Pointers are completely irrelevant here. The `std::array` size is constant, no matter what pointer gets thrown in there. It's utterly irrelevant. – Sam Varshavchik Feb 12 '23 at 13:56
  • A reference may not "allocate a pointer on a heap". What gave you that idea? – molbdnilo Feb 12 '23 at 14:00
  • @SamVarshavchik you are right, I wanted this specialization of the array exactly to know what is the size of the buffer without providing a parameter or use a known magic variable. – Arkady Feb 12 '23 at 14:01
  • @molbdnilo sometimes references are implemented using pointers at some of compilers for some of platforms. I can't name it to you right from my head, but we just have this problem and are restricted to use references at some of projects – Arkady Feb 12 '23 at 14:02
  • 1
    Yes, so, declare a `template struct array_size;`, then a `template struct array_size>`, define a `constexpr` member. Mission accomplished. – Sam Varshavchik Feb 12 '23 at 14:04
  • @molbdnilo quick search gave me this: https://stackoverflow.com/questions/2323189/how-is-a-reference-different-from-a-pointer-in-implementation, not a prove, but something – Arkady Feb 12 '23 at 14:04
  • 1
    You should use `std::declval` to create an instance at compile time., e.g. `std::declval().size()` – Swift - Friday Pie Feb 12 '23 at 14:04
  • @Arkady Yes, they usually are (or, rather, both pointers and references are represented using memory addresses) but that does not imply any free-store allocation. – molbdnilo Feb 12 '23 at 14:04
  • @SamVarshavchik We already have one: [`std::tuple_size`](https://en.cppreference.com/w/cpp/container/array/tuple_size). – Evg Feb 12 '23 at 14:09
  • @Arkady excuse me, but your take out about references can be described only in foul language. One should read specification instead of making assumptions based on anecdotal case. The answer to that question is, formally, incorrect. Informally, it's a greatly misleading one. Reference doesn't allocate memory, it represent an alias to object allocated somewhere else and in some cases a storage for address to provide that alias.The storage class of a reference depends on its context, similar to a variable. There are some special cases when const reference affects object's life span – Swift - Friday Pie Feb 12 '23 at 14:11
  • *because `std::array<...>::size()` is not static* - That's not the reason. The reason is that `a` is a pointer, not value. See [here](https://stackoverflow.com/questions/54124899/why-is-a-constexpr-function-on-a-reference-not-constexpr). If you change `const my_array* a` to `my_array a`, the code will compile. – Evg Feb 12 '23 at 14:15
  • @Swift-FridayPie `my_array().size()` will work, too. – Evg Feb 12 '23 at 14:16
  • @Swift-FridayPie I would appreciate a reference to the Standard requiring compilers to implement mechanism of `references` without any allocation of any additional memory. Then what I had experiences is the bug of the compiler, probably very old and poor written. If we don't have this requirement, then what I had experienced was a valid behavior. Anyway, its not a subject for this question, but if the answer under the link above is incorrect, you can prove it there, and I will be happy to find out that you are right. – Arkady Feb 12 '23 at 14:26
  • @Arkady I can find nothing in the link you posted that suggests that anyone claims that using a reference would lead to any free-store allocation. (Are you perhaps thinking of the "references" of other languages, like Python or Java?) – molbdnilo Feb 12 '23 at 14:58
  • @Arkady references aren't objects , for one. pointer to reference is impossible. "It's unspecified if storing a reference requires storage or not", which completely rules out use of extra free storage for the address. Free store is 100% deterministic. IF stored, reference matches variables in same context. If speaking of referenced object, storing a reference to it doesn't change object's storage. – Swift - Friday Pie Feb 13 '23 at 06:27
  • @Swift-FridayPie I didn't mean to confuse anyone (probably my poor English could), and definitely didn't mean that there may exist a pointer to reference, or object's storage may be changed. I had an impression that reference itself may be stored as a pointer, due to its unspecified, and compiler may do it. We had the measurement stating that, and I had no reasons to disagree due to unspecified matter of the subject. Although I agree with you, that it seems very unlikely to create such a pointer in free store, at least for x86. And now, when you pointed to that, it seems weird. – Arkady Feb 13 '23 at 08:08
  • I slightly modified the question, removed disputable statement, unrelated to the question. – Arkady Feb 13 '23 at 08:12

1 Answers1

1

You can do this:

static_assert(sizeof(*a) < sizeof(b), "text");
John Zwinck
  • 239,568
  • 38
  • 324
  • 436