How to Print Out the Size of a C++ Class at Compile-Time

Is it possible to print out the size of a C++ class at compile-time?

If you really need to to get sizeof(X) in the compiler output, you can use it as a parameter for an incomplete template type:

template<int s> struct Wow;
struct foo {
int a,b;
};
Wow<sizeof(foo)> wow;

$ g++ -c test.cpp
test.cpp:5: error: aggregate ‘Wow<8> wow’ has incomplete type and cannot be defined

Printing sizeof(T) at compile time

Yes. The possible duplicate prints the size as error message, which means the compilation will not succeed.

However, my solution prints the size as warning message, which means, it will print the size, and the compilation will continue.

template<int N> 
struct print_size_as_warning
{
char operator()() { return N + 256; } //deliberately causing overflow
};

int main() {
print_size_as_warning<sizeof(int)>()();
return 0;
}

Warning message:

prog.cpp: In member function ‘char print_size_as_warning<N>::operator()() [with int N = 4]’:
prog.cpp:8: instantiated from here
prog.cpp:4: warning: overflow in implicit constant conversion

Demo : http://www.ideone.com/m9eg3

Note : the value of N in the warning message is the value of sizeof(int)


The above code is improved one, and my first attempt was this:

template<int N> 
struct _{ operator char() { return N+ 256; } }; //always overflow

int main() {
char(_<sizeof(int)>());
return 0;
}

Warning message:

prog.cpp: In member function ‘_<N>::operator char() [with int N = 4]’:
prog.cpp:5: instantiated from here
prog.cpp:2: warning: overflow in implicit constant conversion

Demo : http://www.ideone.com/mhXjU

The idea is taken from my previous answer to this question:

  • Calculating and printing factorial at compile time in C++

See the size of a struct element at compile time?

I regret to say that the following ugly, brute-force methods is all I could come up with. But they work.

Method 1

Compilation fails at the line that corresponds to the size. By checking which line fails, I know the size of the struct element

#define STATIC_ASSERT_SIZE(an_item, a_siz) do { enum { dummy_var = 1/((an_item == a_siz)? 0 : 1 )}; } while (0)

STATIC_ASSERT_SIZE(sizeof(my_struct.element), 0);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 1);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 2);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 3);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 4);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 5);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 6);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 7);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 8);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 9);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 10);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 11);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 12);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 13);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 14);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 15);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 16);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 17);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 18);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 19);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 20);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 21);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 22);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 23);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 24);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 25);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 26);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 27);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 28);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 29);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 31);
STATIC_ASSERT_SIZE(sizeof(my_struct.element), 32);

Method 2

Assuming it compiles, look at the variable in the MAP file generated by the compiler, which tells you how many bytes it uses.

Assert sizeof(obj) at compile time and print the actual size if it doesn't match (c++98)

One way to "display" value at compile time is in the error:

template <std::size_t N> struct Debug; // No definition

template <> struct Debug<1234> {}; // Definition for "old" sizeof;

template struct Debug<sizeof(obj)>; // Issue error if definition is missing

Demo without error

Demo with error

Error message is similar to:

error: explicit instantiation of ‘struct Debug<5678ul>’ before definition of template

C++ Compile time specification of array size

The modern way would be to use a constexpr, to tell the compiler it is an actual compile-time constant. See a simpler example:

constexpr int Size = sizeof(long) * 7;

class Foo
{
int t[Size];
};

or

class Foo
{
static constexpr int Size = sizeof(long) * 7;
int t[Size];
};

Printing a compile-time string_view

Here's a modification of OP's solution that produces a somewhat more readable message with gcc. Unfortunately, with clang the message is rather less readable, and MSVC doesn't work at all (due to a compiler bug I suppose).

#include <cstdlib>
#include <algorithm>
#include <string_view>
#include <utility>

template <size_t N> struct FS { // fixed size string
char chars[N + 1] = {};
constexpr FS(const char (&str)[N + 1]) {
std::copy_n(str, N + 1, chars);
}
};

template <size_t N> FS(const char (&str)[N])->FS<N - 1>;

template<typename T>
struct type_to_string;

template<>
struct type_to_string<int> { constexpr static auto value = "integer"; };

template <auto>
constexpr bool string_value = false;

template<FS fs> // size will be deduced
void compile_time_display() {
static_assert(string_value<fs>);
}

int main()
{
constexpr std::string_view sv = type_to_string<int>::value;
constexpr size_t n = sv.size();
constexpr auto indices = std::make_index_sequence<n>();

[&] <std::size_t... I>
(std::index_sequence<I...>)
{
static constexpr char text[] { (char)sv.at(I)..., 0 };
compile_time_display<text>(); // the char array will convert to FS

}(indices);
}

The message shown by gcc reads:

main.cc: In instantiation of ‘void compile_time_display() 
[with FS<...auto...> fs = FS<7>{"integer"}]’
...
main.cc:26:23: note: ‘string_value<FS<7>{"integer"}>’ evaluates to false

How to deduce the size of a compile time a const char string with C++ templates?

This

char * const begin_;

is a const pointer to char (the pointer is const, not the thing it points to). This

const char(&arr)[N]

is a reference to an array of N elements of type const char. The element of the array are const. You cannot have a pointer to non-const point into an array of const elements (at least not without brute force). You need to either make your pointer a const char* or make your array an array of non-const elements…

I guess you mean to write

const char* begin_;

Note: starting with C++17, you can just use std::string_view

Compile time sizeof_array without using a macro

Try the following from here:

template <typename T, size_t N>
char ( &_ArraySizeHelper( T (&array)[N] ))[N];
#define mycountof( array ) (sizeof( _ArraySizeHelper( array ) ))

int testarray[10];
enum { testsize = mycountof(testarray) };

void test() {
printf("The array count is: %d\n", testsize);
}

It should print out: "The array count is: 10"



Related Topics



Leave a reply



Submit