5

I want to achieve behavior like sizeof(complete_type) will return real sizeof, and sizeof(incomplete_type) - will be just 0

I need this to provide extended run time type information for IPC(inter-process) communication with the description structure per type:

struct my_type_info
{
    bool   is_pointer;
    size_t size;         //for double* will be 4 on i386. that is sizeof(double*)
    size_t base_size;    //for double* will be 8. that is sizeof(double)
};

The problem appears when into my system goes something like class MyOnlyDeclaredClass; I got compilation error, obviously by reason I can't take size of it.

boost type_traits http://www.boost.org/doc/libs/1_48_0/libs/type_traits/doc/html/index.html suggests many compile-time classes, but there is no 'is_incomplete'

Interesting compilers are VS2008, VS2010, clang 3, gcc-4.6, gcc-4.7

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
dev_null
  • 1,907
  • 1
  • 16
  • 25
  • 2
    And what are you going to do if you detect that the type is incomplete? Throw a static_assert error? – Karel Petranek Dec 09 '11 at 17:08
  • No if pointer lays in shared memory, I can just pass it to another process without knowing what it is the type. Pointer can be easy passed by subtraction shared memory base from its value. – dev_null Dec 09 '11 at 17:13
  • 1
    I still don't seem to understand it. Why don't you pass all the pointers (both of complete and incomplete types) that way? – Karel Petranek Dec 09 '11 at 17:15
  • because in my system presents another kind of pointers - like interfaces that should be passed to another process in another way. Additionally it will allow to check at runtime from which kind of memory the pointer goes. I admit an ability to resolve task in another not so much elegant way. – dev_null Dec 09 '11 at 17:19
  • Please tell us more about what you really need to do. – curiousguy Dec 10 '11 at 00:16

2 Answers2

12

Do not try to do that.

It is fundamentally unsound. Templates are parametrized by types, not instantiation point. A class type is not complete or not in itself, it is complete at some point during translation.

A template instantiated on some types must have the exact same semantic in every instantiation.

If not, the behaviour is not defined.

curiousguy
  • 8,038
  • 2
  • 40
  • 58
  • 5
    +1. I was just about to scream like that too. The while idea is fundamentally broken. – Johannes Schaub - litb Dec 10 '11 at 00:28
  • 1
    Well, I actually have a reasonably valid usecase for this. I've been doing a little wrapper-generator tool that exports C++ functions to other languages, and I decided to not even try to parse C++ but use variadic templates to take the function declarations apart. In some of these cases I now use the is_complete to check whether certain classes are derived "as required", and just assume they are if the classes aren't known to the wrapper tool. Compiling the C++ will fail anyway if the classes are not according to specs; it just fails earlier if the tool can already do the check. – Christian Stieber Jun 03 '16 at 13:47
4

Use SFINAE, as usual. This is one possible implementation:

struct char256 { char x[256]; };

template <typename T>
char256 is_complete_helper(int(*)[sizeof(T)]);

template <typename>
char is_complete_helper(...);

template <typename T>
struct is_complete
{
    enum { value = sizeof(is_complete_helper<T>(0)) != 1 };
};

Example:

#include <cstdio>

struct F;
struct G {};

int main()
{
    printf("%d %d\n", is_complete<F>::value, is_complete<G>::value);
    return 0;
}

(Note: Works on gcc 4.5 (no it's not because of C++0x) and clang 2.9, but not gcc 4.3)

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005