How to Implement an Autonomous 'Self' Member Type in C++

Can I implement an autonomous `self` member type in C++?

Here's how you can do it without repeating the type of Foo:

template <typename...Ts>
class Self;

template <typename X, typename...Ts>
class Self<X,Ts...> : public Ts...
{
protected:
typedef X self;
};

#define WITH_SELF(X) X : public Self<X>
#define WITH_SELF_DERIVED(X,...) X : public Self<X,__VA_ARGS__>

class WITH_SELF(Foo)
{
void test()
{
self foo;
}
};

If you want to derive from Foo then you should use the macro WITH_SELF_DERIVED in the following way:

class WITH_SELF_DERIVED(Bar,Foo)
{
/* ... */
};

You can even do multiple inheritance with as many base classes as you want (thanks to variadic templates and variadic macros):

class WITH_SELF(Foo2)
{
/* ... */
};

class WITH_SELF_DERIVED(Bar2,Foo,Foo2)
{
/* ... */
};

I have verified this to work on gcc 4.8 and clang 3.4.

OOP in C, implicitly pass self as parameter

I can't wrap my head around how to structure my "object" so instead of

Stopwatch->tick(Stopwatch);

I can write Stopwatch->tick();

This is not possible in standard C. You need to pass the receiver as an explicit formal argument to your C functions (in contrast with C++ which has this as an implicit formal).

However:

  • you generally want to pack all the method functions in one single struct with several function members (and have each instance start with a pointer to that struct). Read about vtable-s.

  • you could have some macro (or perhaps inline function) to avoid giving Stopwatch twice; you'll still write TICK(Stopwatch) not Stopwatch->tick();; the statement-expr extension of GCC could be useful.

Look into GTK and its Gobject system as an example of a cute object system for C. Read also about the ObjVLisp model and wikipage on virtual method tables. Maybe see this draft report and RefPerSys and also the blog of the late J.Pitrat.

BTW, you could decide that you have first class method selectors (perhaps as integers, or pointers to some common selector type) and code a variadic send dispatching function (so you would code send(StopWatch,TICK_SEL) instead of your dreamed Stopwatch->tick()) or macro. You might find libffi useful. The old Xview could be inspirational.

At last, as many fancy object layer implementors, you might use some metaprogramming and provide some C code generating tool (like moc in Qt). You might even consider customizing your GCC compiler with MELT for such purposes. Or making a translator (see this) from your fancy OOP dialect to C (like VALA or SWIG or Bigloo or Chicken-Scheme do; see also this). Or preprocess your code with an external preprocessor (your own one, or m4 or GPP, etc...).

How to extract the type of an unnamed struct to create a new type within the struct itself?

Something like this, maybe?

The idea is that you actually have two unnamed structs. Firstly, unnamed contains all the actual code/data and stuff. Then there is unnamedWrapper that, being able to use decltype over unnamed, is just a completely-forwarding (even for constructors!) wrapper around unnamed, with the single speciality that it exports unnamed's type through a typedef.

#include <cstddef>

template<typename T>
size_t templatedSizeof() {
return sizeof(T);
}

struct {
char something;
short somethingElse;
int moreGargabe;
long evenMoreUselessGarbage;
} unnamed;

struct : public decltype(unnamed) {
typedef decltype(unnamed) TheType;

using TheType::TheType; // Use same constructors
} unnamedWrapper;

Explicitly access static member variable in static member method - in C++

Is there something like self:: in C++ ?

No there is no such feature, but you can use a class local typedef:

class MyClass {
typedef MyClass self;
static int testValue;
static int getTestValue1(){
return self::testValue;
}
};

See a working demo.

Detect the existence of a template instantiation for a given type

Here's a link-time solution. Works on GCC, Clang, and MSVC.

One template (impl::Checker<T>) declares a friend function and calls it.

Another template (impl::Marker) defines that function. If it's not defined, the first class gets an undefined reference.

run on gcc.godbolt.org

#include <cstddef>
#include <type_traits>


namespace impl
{
template <typename T>
struct Checker
{
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-template-friend"
#endif
friend void adl_MarkerFunc(Checker<T>);
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif

static std::nullptr_t Check()
{
adl_MarkerFunc(Checker<T>{});
return nullptr;
}

inline static const std::nullptr_t check_var = Check();
static constexpr std::integral_constant<decltype(&check_var), &check_var> use_check_var{};
};


template <typename T>
struct Marker
{
friend void adl_MarkerFunc(Checker<T>) {}
};
}


template <typename T, impl::Checker<T> = impl::Checker<T>{}>
struct Access
{
template <typename U>
void Read()
{
static_assert(std::is_same_v<T, U>);
(void)impl::Marker<U>{};
}
};


int main()
{
Access<int> x;
x.Read<int>();

[[maybe_unused]] Access<float> y; // undefined reference to `impl::adl_MarkerFunc(impl::Checker<float>)'

using T [[maybe_unused]] = Access<double>; // undefined reference to `impl::adl_MarkerFunc(impl::Checker<double>)'
}

Had to introduce a dummy template parameter to Access, since I couldn't think of any other way of detecting it being used in a using.

C++ - Are there ways to get current class type with invariant syntax?

You can use the following trick:

#define SELF \
static auto helper() -> std::remove_reference<decltype(*this)>::type; \
typedef decltype(helper()) self

struct A {
SELF;
};

I declare a helper function using the auto return type, which allows me to use decltype(*this) as a return type, not knowing what is the class name. Then I can use decltype(helper()) to use the class type in the code. Note that the function has to be static, otherwise you can not use it in decltype. Also the function is just declared, not defined; this should not be a problem as you are not going to call it anyway. (You can add an empty body to it, but it will raise a warning that a function has no return. Still you may change the return type to be decltype(this) and return nullptr.)

You may then use the self typedef for further declarations, or just alter the macros to typedef not the class itself, but what you need to. Adjust it to suit your particular need.

UPD: This seems to be a non-standard behavior of GCC. For example, ICC does not allow this in static functions even in trailing return type.



Related Topics



Leave a reply



Submit