0

I am trying to update C/C++ code, want to use getters and setters for tracking and/or testing.

Made a template class for general declarations

#include <iostream>

using namespace std;

#define TRACK_PROP(a,b) TrackProp<a> b(#b);
#define TRACK_PROP_SET(a,b,c) TrackProp<a> b(#b, c);

template <class T>
class TrackProp {
public:
    T _content;
    const char* Name;

    TrackProp(const char* name) { Name = name; }
    TrackProp(const char* name, T val) { Name = name; _content = val; }
    T operator =(T right)
    {
        if (_content != right) {
            cout << Name << ":" << _content << "->" << right << endl;
            _content = right;
        }
        return _content;
    }

    operator T() const
    {
        return _content;
    }

    T operator ++()
    {
        operator = (_content + 1);
        return _content;
    }
    T operator ++(int)
    {
        operator = (_content + 1);
        return _content - 1;
    }
    T operator --()
    {
        operator = (_content - 1);
        return _content;
    }
    T operator --(int)
    {
        operator = (_content - 1);
        return _content + 1;
    }
    T operator +=(int right)
    {
        operator = (_content + right);
        return _content;
    }
    T operator -=(int right)
    {
        operator = (_content - right);
        return _content;
    }
};

I can easily translate declarations now

int foo;
int bar = 2;

// These 2 or even some object can be declared by
TRACK_PROP(int, foo);
TRACK_PROP_SET(int, bar, 2);
foo = 1; // = operator /setter
int baz;
baz = bar; // () operator /getter

But having problems when they are used in C files too.

How would you change it to keep Get/Set/Name functionality and be able to use it also in C files as simply as in C++ ?

Jan
  • 2,178
  • 3
  • 14
  • 26
  • Looks similar like property answers https://stackoverflow.com/questions/8368512/does-c11-have-c-style-properties#35478633, https://stackoverflow.com/questions/4225087/c-like-properties-in-native-c#4225302, etc. – Jan Jul 31 '21 at 09:18

2 Answers2

3

C does not have operator overloading, and C operators are not valid macro names, so there is no way to automagically convert any C operation into a function call. You can certainly implement getters and setters (as top-level functions, because C does not have methods / member functions, either), but they would need to be explicitly declared and explicitly called.

As far as I understand what you are trying to achieve, then, it's not going to work at all in C. You would need to manually instrument your C sources to get something similar to what your template is giving you on that side.

Addendum

There seems to be some confusion about the significance of having both C and C++ code in the same project. In particular, there seems to be an idea that it has significance. It doesn't, at least none that applies to the question.

C source files are compiled by a C compiler, and that defines the language features available to those translation units. C++ sources are compiled by a C++ compiler, and that defines the language features available within those translation units. Functions on one side can call functions on the other side, with some caveats, but that's not dependent on belonging to the same project. And it's not sufficient for getting your auto getter/setter trick to apply to C code.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
1

I am a not expert, but isn't it too complicated to generate C++/C functions and replace your variable by some macro ? Your a bit modified version:

#ifdef __cplusplus
#define TRACK_C(a, b) \
extern "C" a _get$##b() { \
return b; \
}; \
extern "C" void _set$##b(a c) { \
##b = c; \
};
#define TRACK_PROP(a,b) TrackProp<a> b(#b); \
TRACK_C(a, b)
#define TRACK_PROP_SET(a,b,c) TrackProp<a> b(#b, c); \
TRACK_C(a, b)
template <class T>
class TrackProp {
public:
    T _content;
    const char* Name;

    TrackProp(const char* name) { Name = name; }
    TrackProp(const char* name, T val) { Name = name; _content = val; }
    T operator =(T right)
    {
        if (_content != right) {
            cout << Name << ":" << _content << "->" << right << endl;
            _content = right;
        }
        return _content;
    }

    operator T() const
    {
        return _content;
    }
};
#else
#define TRACK_C(a,b) \
a _get$##b(); \
void _set$##b(a);
#define TRACK_GET(b) _get$##b()
#define TRACK_SET(b,c) _set$##b(c)
#endif

In C++ you can still use you operators

#include <iostream>
#include "TRACK_PROP.h"

using namespace std;

TRACK_PROP(int, demo);

extern "C" void test();

void main(void) {
    demo = 123;
    cout << demo;
    test();
}

And in C replace a demo variable use by my macros:

#include "TRACK_PROP.h"

TRACK_C(int, demo)

void test() {
    // demo = 1
    TRACK_SET(demo, 1);
    // demo = 3*demo;
    TRACK_SET(demo, 3*TRACK_GET(demo)));
}

It would be great if there will be easier option, but I do not know about any direct way too...

Jaroslav
  • 26
  • 2