A question similar to the for_each
in std::tuple
given here, but not exactly.
Intuitively, I would like a "tuple" of pointers formed from a sequence of variables, and I want to "iterate" on that "tuple"...
It is in context of coding a naive mark and sweep precise garbage collector in C++14 (on Linux/Debian/Sid, either with GCC 4.9 or soon released 5.0 or with Clang/LLVM 3.5 or just released 3.6).
I don't want to use Boost.
I have two unrelated classes : PtrItem
and Value
. The PtrItem
class is a "pointer-like" class containing only one field Item* itemptr;
. the Value
class contains a discriminated union (see here). Both classes PtrItem
and Value
have a method
void scan_items(std::function<void(PtrItem)> f) const;
Suppose I have a block starting with
{
PtrItem pit1, pit2;
Value valx, valy;
I want to write just after that in the same block
GCROOT(pit1,pit2,valx,valy); /// at line 456
with
class ProtoGcRoot {
const char* gcrfile;
int gcrline;
ProtoGcRoot* gcrprev;
protected:
template <typename T1, typename... Args> class GcData
{
T1* ptr;
GcData<Args...> rest;
public:
GcData(T1& v, Args... args) : ptr(&v), rest(args...) {};
~GcData() { ptr = nullptr; };
void scan_gc_data(std::function<void(PtrItem)> f) {
if (ptr) ptr->scan_items(f);
rest.scan_gc_data(f);
}
};
template <> class GcData
{ GcData() {};
~GcData() {};
void scan_gc_data(std::function<void(PtrItem)>) {};
};
ProtoGcRoot(const char*fil, int lin);
ProtoGcRoot() = delete;
ProtoGcRoot(const ProtoGcRoot&) = delete;
ProtoGcRoot(ProtoGcRoot&&) = delete;
ProtoGcRoot& operator = (const ProtoGcRoot&) = delete;
virtual ~ProtoGcRoot();
public:
virtual void scan_gc_items (std::function<void(PtrItem)>)= 0;
}; // end class ProtoGcRoot
template<typename... Args>
class GcRoot : ProtoGcRoot {
ProtoGcRoot::GcData<Args...> gcdata;
public:
GcRoot(const char*fil, int lin, Args... rest)
: ProtoGcRoot(fil,lin), gcdata(rest...) {};
~GcRoot() {};
virtual void scan_gc_items (std::function<void(PtrItem)> f) {
gcdata.scan_gc_data(f);
}
};
#define GCROOT_AT(Fil,Lin,...) GcRoot gc_root_##Lin{Fil,Lin,__VA_ARGS__}
#define GCROOT(...) GCROOT_AT(__FILE__,__LINE__,__VA_ARGS__)
The intent is to have a gc_root_456
variable with an equivalent of
void scan_gc_items (std::function<void(PtrItem)>f) {
pit1.scan_items(f);
pit2.scan_items(f);
val1.scan_items(f);
val2.scan_items(f);
}
But my code does not compile:
./yacax.h:729:3: error: extraneous 'template<>' in declaration of class 'GcData'
template <> class GcData
^
./yacax.h:729:21: error: redefinition of 'GcData' as different kind of symbol
template <> class GcData
^
./yacax.h:717:50: note: previous definition is here
template <typename T1, typename... Args> class GcData
^
The GcData
class is internal in ProtoGcRoot
because I don't feel it should be exposed.