Stateless lambdas as static local variable - c++

I am trying to write a templated wrapper class around a stateless lambda. Something like this:
template <class TFuncOp>
class Adapter
{
public:
void Op()
{
TFuncOp func; // not possible before C++20
func();
}
};
Since this isn't possible before default constructible lambdas arrive with C++20, I used this technique to make my class work: Calling a stateless lambda without an instance (only type)
So the final solution looks like this:
template <class TFuncOp>
class Adapter
{
public:
static TFuncOp GetOpImpl( TFuncOp *pFunc = 0 )
{
static TFuncOp func = *pFunc;
return func;
}
void Op()
{
GetOpImpl()();
}
};
template <class TFuncOp>
Adapter<TFuncOp> MakeAdapter(TFuncOp func )
{
// Removing the line below has no effect.
//Adapter<TFuncOp>::GetOpImpl( &func );
return Adapter<TFuncOp>();
}
int main()
{
auto adapter = MakeAdapter( [] { printf("Hello World !\n"); } );
adapter.Op();
return 0;
}
This code works on all major compilers (clang, gcc, msvc). But with one surprising discovery. Initialization (or lack thereof) of the static local instance of the lambda in GetOpImpl() has no effect. It works fine either way.
Can anyone explain how this works? Am I invoking UB if I use the static local instance of the lambda without initializing it?

In any case, accessing a nullptr is never a good idea as it is UB.
But we can see that typical implementations generate code which simply works. I try to explain why:
First, it has nothing to do with lambdas. It is simply the not needed using of a copy constructor on a class which has no data. As you have no data, the generated code will not access the passed object. In your case, you "copy" the object which the pointer TFuncOp *pFunc = 0 points to, which is a nullptr which will crash if the object must be accessed. As there is no data to access, a typical implementation will not genrate any code which will access the nullptr at all. But it is still UB.
The same works with all other types in the same way and has nothing special with a lambda!
struct Empty
{
void Do() { std::cout << "This works the same way" << std::endl; }
// int i; // << if you add some data, you get a seg fault
};
int main()
{
Empty* ptr = nullptr;
Empty empty = *ptr; // get seg fault here, because default copy constructor access the nullptr, but typically only if copy ctor needs to access!
empty.Do();
}
And a lambda which has no captured data, is an empty structure with a operator()().
That all is a answer why it seems to work.

Related

Overload -> arrow operator in shared_ptr<interface> instance with no pure virtual destructor in interface

I'm trying to overload the -> operator to eventually execute something along the lines:
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle(); //this works wonderfully
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
//the next line doesn't compile, I would like to achieve something like this, but even
//sharedPtrWrapper.get()->Toggle();
//would be nice to achieve, is this possible?
sharedPtrWrapper->Toggle();
//this works:
sharedPtrWrapper->operator->()->Toggle();
Note: I have no control over MyInterface, cannot implement the pure virtual destructor.
Here is what I tried (the below code runs):
#import <memory>
#import <iostream>
struct MyInterface {
virtual bool Toggle() = 0;
};
class A : public MyInterface {
public:
bool Toggle() {
stateEnabled = !stateEnabled;
std::cout<<"current state " << stateEnabled << std::endl;
return true;
}
private:
bool stateEnabled = false;
};
template <typename T>
class Wrapper {
private:
T *unsafePointer = nullptr;
public:
Wrapper<T>()
{ }
T *operator->() const {
return unsafePointer;
}
T *getInner() {
return unsafePointer;
}
Wrapper<T>(T *stuff) {
unsafePointer = stuff;
}
~Wrapper<T>() {}
};
int main(int argc, const char * argv[]) {
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle();
Wrapper<MyInterface> wrapperS(myInstance);
wrapperS->Toggle();
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
sharedPtrWrapper->operator->()->Toggle();
sharedPtrWrapper.operator->()->operator->()->Toggle();
sharedPtrWrapper.get()->operator->()->Toggle();
(*sharedPtrWrapper).operator->()->Toggle();
return 0;
}
Output:
current state 1
current state 0
current state 1
current state 0
current state 1
current state 0
Program ended with exit code: 0
To reiterate:
This code doesn't compile:
sharedPtrWrapper->Toggle();
How to make it compile?
Edit : I'm using a wrapper because I have no control over the MyInterface, I get it from a library, also shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>(myInstance); doesn't compile, because of the missing pure virtual destructor from the above mentioned interface.
Edit2: Example library usage in pseudocode:
void firstcallbackFromLib(Framework *framework) {
MyInterface *myInstance = framework->getInstance();
{
Wrapper<MyInterface> wrapperS(myInstance);
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(wrapperS);
//assign sharedPtrWrapper and framework to static instances
}
}
void myFunction() {
sharedPtrWrapper->Toggle(); //this doesn't work, this is what i'm trying to achieve
sharedPtrWrapper->operator->()->Toggle(); //this ugly thing works
}
void lastUninitCallbackFromLibrary() {
MyInterface *p = sharedPtrWrapper.get()->getInner();
framework->releaseInterface(p);
//etc
}
The problem is, that shared_ptr behaves like a pointer and Wrapper does that as well. In summary, you have code that behaves like a pointer to a pointer. In short, you could call (*sharedPtrWrapper)->Toggle(); instead of the abomination sharedPtrWrapper->operator->()->Toggle();.
Careful though: It's unclear what all this is supposed to achieve, because the example code is just an abstraction of your actual code. So, maybe it would just be more elegant to put a forwarding Toggle() method into class Wrapper, but that's impossible to tell with the info provided here.
I am confused about the question. Why wrapper class that does nothing?
If you want to put a class inside shared pointer yet do something uncommon at destruction: like, calling dll's function that performs the destruction, do some preprocessing, perform file closure instead of delete, or do nothing at all if that's what you want. Then you can simply specify it at shared pointer instantiation:
https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr - see construction option 5.
You don't need your wrapper at all.
shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>();
wont work because MyInterface is an abstract class. But, just like you can do
MyInterface *myInstance = new A();
To have a MyInterface * that points to a concrete derived object, you can use
std::shared_ptr<MyInterface> sharedPtr = std::make_shared<A>();
To get a std::shared_ptr<MyInterface> that points to a concrete derived object. You can then use sharedPtr to access Toggle like
sharedPtr->Toggle();
You can see that working in this live example
sharedPtrWrapper->Toggle(); doesn't compile because of operator-> chaining rules explained well in this answer. In principle: if your object is NOT a pointer, operator-> is called recursively, if it is a pointer, member access is performed. Now std::shared_ptr has overloaded operator-> to access the raw Wrapper<MyInterface>* pointer kept inside and when it is applied on it, it tries to access Toggle, which does not exist.
For clarity note that this code also will not compile:
Wrapper<MyInterface>* wrapper = new Wrapper<MyInterface>(myInstance);
wrapper->Toggle();
You can do this however:
(*sharedPtrWrapper)->Toggle();
Use:
struct CleanupMyInterface {
SomeTypeFromLib* somePointerFromLib = nullptr;
void operator()( MyInterface* ptr ) const {
if (somePointerFromLib && ptr)
somePointerFromLib->releaseInterface(ptr);
}
};
std::shared_ptr<MyInterface> sharedPtr( CreateAnInstanceOfAFromLibrary(), CleanupMyInterface{somePointerFromLib} );
shared_ptr has type-erased destruction, there is no need for a virtual destructor.

Avoid use of undefined object in c++

If I create a class in c++, it is possible to call a function of an object of this class, even if this class does not exists.
For example:
Class:
class ExampleClass
{
private:
double m_data;
public:
void readSomeData(double param)
{
m_data = param;
}
}
Any function where this class is used:
int main()
{
ExampleClass* myClass;
myClass->readSomeData(2.5);
}
Ofcourse this wouldn't function, because myClass is not defined.
To avoid such situations, I check if ExampleClass objects are a null_ptr
example:
void readSomeData(double param)
{
if(this == null_ptr)
return;
m_data = param;
}
But gcc says:
'this' pointer cannot be null in well-defined C++ code; comparison may
be assumed to always avaluate to false.
Ofcourse that is only a warning, but I think it is not nice to have this warning. Is there a better way to check if the pointer of a class is defined?
Testing it in the class is the wrong way, the warning is correct about that if your code is well defined then this must not be null, so the test should happen at the time when you call the member function:
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
if (myClass != nullptr) {
myClass->readSomeData(2.5);
}
return 0;
}
If a pointer must not be null at a certain part of your code then you should do it according to CppCoreGuideline: I.12: Declare a pointer that must not be null as not_null
Micorosoft provides an Guidelines Support Library that has an implementation for not_null.
Or if possible then don't use pointers at all but std::optional.
So a code setup could look like this:
#include <gsl/gsl>
struct ExampleClass {
void readSomeData(double ){}
};
// now it is clear that myClass must not and can not be null within work_with_class
// it still could hold an invalid pointe, but thats another problem
void work_with_class(gsl::not_null<ExampleClass*> myClass) {
myClass->readSomeData(2.5);
}
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
work_with_class(myClass);
return 0;
}
The best way is not use pointers at all:
int main()
{
ExampleClass myClass;
myClass.readSomeData(2.5);
}
That way there's no need for any check, and in fact, checking this inside the function is moot.
If you need nullability, use std::optional instead.
Either don't use pointers as Bartek Banachewicz has pointed out, or properly initialize and check the pointer:
int main()
{
ExampleClass* myClass= 0;
if (myClass)
myClass->readSomeData(2.5);
return 0;
}
Of course you still have to add the instantiation of the object at some point, otherwise the code is nonsense.

Avoid memory allocation with std::function and member function

This code is just for illustrating the question.
#include <functional>
struct MyCallBack {
void Fire() {
}
};
int main()
{
MyCallBack cb;
std::function<void(void)> func = std::bind(&MyCallBack::Fire, &cb);
}
Experiments with valgrind shows that the line assigning to func dynamically allocates about 24 bytes with gcc 7.1.1 on linux.
In the real code, I have a few handfuls of different structs all with a void(void) member function that gets stored in ~10 million std::function<void(void)>.
Is there any way I can avoid memory being dynamically allocated when doing std::function<void(void)> func = std::bind(&MyCallBack::Fire, &cb); ? (Or otherwise assigning these member function to a std::function)
Unfortunately, allocators for std::function has been dropped in C++17.
Now the accepted solution to avoid dynamic allocations inside std::function is to use lambdas instead of std::bind. That does work, at least in GCC - it has enough static space to store the lambda in your case, but not enough space to store the binder object.
std::function<void()> func = [&cb]{ cb.Fire(); };
// sizeof lambda is sizeof(MyCallBack*), which is small enough
As a general rule, with most implementations, and with a lambda which captures only a single pointer (or a reference), you will avoid dynamic allocations inside std::function with this technique (it is also generally better approach as other answer suggests).
Keep in mind, for that to work you need guarantee that this lambda will outlive the std::function. Obviously, it is not always possible, and sometime you have to capture state by (large) copy. If that happens, there is no way currently to eliminate dynamic allocations in functions, other than tinker with STL yourself (obviously, not recommended in general case, but could be done in some specific cases).
As an addendum to the already existent and correct answer, consider the following:
MyCallBack cb;
std::cerr << sizeof(std::bind(&MyCallBack::Fire, &cb)) << "\n";
auto a = [&] { cb.Fire(); };
std::cerr << sizeof(a);
This program prints 24 and 8 for me, with both gcc and clang. I don't exactly know what bind is doing here (my understanding is that it's a fantastically complicated beast), but as you can see, it's almost absurdly inefficient here compared to a lambda.
As it happens, std::function is guaranteed to not allocate if constructed from a function pointer, which is also one word in size. So constructing a std::function from this kind of lambda, which only needs to capture a pointer to an object and should also be one word, should in practice never allocate.
Run this little hack and it probably will print the amount of bytes you can capture without allocating memory:
#include <iostream>
#include <functional>
#include <cstring>
void h(std::function<void(void*)>&& f, void* g)
{
f(g);
}
template<size_t number_of_size_t>
void do_test()
{
size_t a[number_of_size_t];
std::memset(a, 0, sizeof(a));
a[0] = sizeof(a);
std::function<void(void*)> g = [a](void* ptr) {
if (&a != ptr)
std::cout << "malloc was called when capturing " << a[0] << " bytes." << std::endl;
else
std::cout << "No allocation took place when capturing " << a[0] << " bytes." << std::endl;
};
h(std::move(g), &g);
}
int main()
{
do_test<1>();
do_test<2>();
do_test<3>();
do_test<4>();
}
With gcc version 8.3.0 this prints
No allocation took place when capturing 8 bytes.
No allocation took place when capturing 16 bytes.
malloc was called when capturing 24 bytes.
malloc was called when capturing 32 bytes.
Many std::function implementations will avoid allocations and use space inside the function class itself rather than allocating if the callback it wraps is "small enough" and has trivial copying. However, the standard does not require this, only suggests it.
On g++, a non-trivial copy constructor on a function object, or data exceeding 16 bytes, is enough to cause it to allocate. But if your function object has no data and uses the builtin copy constructor, then std::function won't allocate.
Also, if you use a function pointer or a member function pointer, it won't allocate.
While not directly part of your question, it is part of your example.
Do not use std::bind. In virtually every case, a lambda is better: smaller, better inlining, can avoid allocations, better error messages, faster compiles, the list goes on. If you want to avoid allocations, you must also avoid bind.
I propose a custom class for your specific usage.
While it's true that you shouldn't try to re-implement existing library functionality because the library ones will be much more tested and optimized, it's also true that it applies for the general case. If you have a particular situation like in your example and the standard implementation doesn't suite your needs you can explore implementing a version tailored to your specific use case, which you can measure and tweak as necessary.
So I have created a class akin to std::function<void (void)> that works only for methods and has all the storage in place (no dynamic allocations).
I have lovingly called it Trigger (inspired by your Fire method name). Please do give it a more suited name if you want to.
// helper alias for method
// can be used in user code
template <class T>
using Trigger_method = auto (T::*)() -> void;
namespace detail
{
// Polymorphic classes needed for type erasure
struct Trigger_base
{
virtual ~Trigger_base() noexcept = default;
virtual auto placement_clone(void* buffer) const noexcept -> Trigger_base* = 0;
virtual auto call() -> void = 0;
};
template <class T>
struct Trigger_actual : Trigger_base
{
T& obj;
Trigger_method<T> method;
Trigger_actual(T& obj, Trigger_method<T> method) noexcept : obj{obj}, method{method}
{
}
auto placement_clone(void* buffer) const noexcept -> Trigger_base* override
{
return new (buffer) Trigger_actual{obj, method};
}
auto call() -> void override
{
return (obj.*method)();
}
};
// in Trigger (bellow) we need to allocate enough storage
// for any Trigger_actual template instantiation
// since all templates basically contain 2 pointers
// we assume (and test it with static_asserts)
// that all will have the same size
// we will use Trigger_actual<Trigger_test_size>
// to determine the size of all Trigger_actual templates
struct Trigger_test_size {};
}
struct Trigger
{
std::aligned_storage_t<sizeof(detail::Trigger_actual<detail::Trigger_test_size>)>
trigger_actual_storage_;
// vital. We cannot just cast `&trigger_actual_storage_` to `Trigger_base*`
// because there is no guarantee by the standard that
// the base pointer will point to the start of the derived object
// so we need to store separately the base pointer
detail::Trigger_base* base_ptr = nullptr;
template <class X>
Trigger(X& x, Trigger_method<X> method) noexcept
{
static_assert(sizeof(trigger_actual_storage_) >=
sizeof(detail::Trigger_actual<X>));
static_assert(alignof(decltype(trigger_actual_storage_)) %
alignof(detail::Trigger_actual<X>) == 0);
base_ptr = new (&trigger_actual_storage_) detail::Trigger_actual<X>{x, method};
}
Trigger(const Trigger& other) noexcept
{
if (other.base_ptr)
{
base_ptr = other.base_ptr->placement_clone(&trigger_actual_storage_);
}
}
auto operator=(const Trigger& other) noexcept -> Trigger&
{
destroy_actual();
if (other.base_ptr)
{
base_ptr = other.base_ptr->placement_clone(&trigger_actual_storage_);
}
return *this;
}
~Trigger() noexcept
{
destroy_actual();
}
auto destroy_actual() noexcept -> void
{
if (base_ptr)
{
base_ptr->~Trigger_base();
base_ptr = nullptr;
}
}
auto operator()() const
{
if (!base_ptr)
{
// deal with this situation (error or just ignore and return)
}
base_ptr->call();
}
};
Usage:
struct X
{
auto foo() -> void;
};
auto test()
{
X x;
Trigger f{x, &X::foo};
f();
}
Warning: only tested for compilation errors.
You need to thoroughly test it for correctness.
You need to profile it and see if it has a better performance than other solutions. The advantage of this is because it's in house cooked you can make tweaks to the implementation to increase performance on your specific scenarios.
As #Quuxplusone mentioned in their answer-as-a-comment, you can use inplace_function here. Include the header in your project, and then use like this:
#include "inplace_function.h"
struct big { char foo[20]; };
static stdext::inplace_function<void(), 8> inplacefunc;
static std::function<void()> stdfunc;
int main() {
static_assert(sizeof(inplacefunc) == 16);
static_assert(sizeof(stdfunc) == 32);
inplacefunc = []() {};
// fine
struct big a;
inplacefunc = [a]() {};
// test.cpp:15:24: required from here
// inplace_function.h:237:33: error: static assertion failed: inplace_function cannot be constructed from object with this (large) size
// 237 | static_assert(sizeof(C) <= Capacity,
// | ~~~~~~~~~~^~~~~~~~~~~
// inplace_function.h:237:33: note: the comparison reduces to ‘(20 <= 8)’
}

Pointer-to-Function and Pointer-to-Object Semantics

I'm having issues with getting a partially-qualified function object to call later, with variable arguments, in another thread.
In GCC, I've been using a macro and typedef I made but I'm finishing up my project an trying to clear up warnings.
#define Function_Cast(func_ref) (SubscriptionFunction*) func_ref
typedef void(SubscriptionFunction(void*, std::shared_ptr<void>));
Using the Function_Cast macro like below results in "warning: casting between pointer-to-function and pointer-to-object is conditionally-supported"
Subscriber* init_subscriber = new Subscriber(this, Function_Cast(&BaseLoaderStaticInit::init), false);
All I really need is a pointer that I can make a std::bind<function_type> object of. How is this usually done?
Also, this conditionally-supported thing is really annoying. I know that on x86 my code will work fine and I'm aware of the limitations of relying on that sizeof(void*) == sizeof(this*) for all this*.
Also, is there a way to make clang treat function pointers like data pointers so that my code will compile? I'm interested to see how bad it fails (if it does).
Relevant Code:
#define Function_Cast(func_ref) (SubscriptionFunction*) func_ref
typedef void(SubscriptionFunction(void*, std::shared_ptr<void>));
typedef void(CallTypeFunction(std::shared_ptr<void>));
Subscriber(void* owner, SubscriptionFunction* func, bool serialized = true) {
this->_owner = owner;
this->_serialized = serialized;
this->method = func;
call = std::bind(&Subscriber::_std_call, this, std::placeholders::_1);
}
void _std_call(std::shared_ptr<void> arg) { method(_owner, arg); }
The problem here is that you are trying to use a member-function pointer in place of a function pointer, because you know that, under-the-hood, it is often implemented as function(this, ...).
struct S {
void f() {}
};
using fn_ptr = void(*)(S*);
void call(S* s, fn_ptr fn)
{
fn(s);
delete s;
}
int main() {
call(new S, (fn_ptr)&S::f);
}
http://ideone.com/fork/LJiohQ
But there's no guarantee this will actually work and obvious cases (virtual functions) where it probably won't.
Member functions are intended to be passed like this:
void call(S* s, void (S::*fn)())
and invoked like this:
(s->*fn)();
http://ideone.com/bJU5lx
How people work around this when they want to support different types is to use a trampoline, which is a non-member function. You can do this with either a static [member] function or a lambda:
auto sub = new Subscriber(this, [](auto* s){ s->init(); });
or if you'd like type safety at your call site, a templated constructor:
template<typename T>
Subscriber(T* t, void(T::*fn)(), bool x);
http://ideone.com/lECOp6
If your Subscriber constructor takes a std::function<void(void))> rather than a function pointer you can pass a capturing lambda and eliminate the need to take a void*:
new Subscriber([this](){ init(); }, false);
it's normally done something like this:
#include <functional>
#include <memory>
struct subscription
{
// RAII unsubscribe stuff in destructor here....
};
struct subscribable
{
subscription subscribe(std::function<void()> closure, std::weak_ptr<void> sentinel)
{
// perform the subscription
return subscription {
// some id so you can unsubscribe;
};
}
//
//
void notify_subscriber(std::function<void()> const& closure,
std::weak_ptr<void> const & sentinel)
{
if (auto locked = sentinel.lock())
{
closure();
}
}
};

Accessing variable outside scope of a callback c++

I have been beating my head around this issue of static versus non-static, callback functions, function pointers, etc... My goal is to access data of a struct outside the scope of my callback interface. I am trying to do this within my class called TextDetect. I thought I was on track when I asked this question: Avoiding a static member function in c++ when using a callback interface from C
However, I still can't access the data without losing scope over the data that I am most interested. At runtime, I get "Access violation reading location ..." I'll point it out below where it fails.
I implemented the answer to my previous question as the following class, shown entirely (Note: vtrInitialize is part of a 3rd party api code int vtrInitialize(const char *inifile, vtrCallback cb, void *calldata);):
class TextDetect {
const char * inifile;
vtrImage *vtrimage;
int framecount;
public:
TextDetect();
~TextDetect();
void vtrCB(vtrTextTrack *track);
static void vtrCB_thunk(vtrTextTrack *track, void *calldata);
int vtrTest(cv::Mat);
bool DrawBox(cv::Mat&);
vtrTextTrack *texttrack;
};
TextDetect::TextDetect() : inifile("vtr.ini")
{
if (vtrInitialize(inifile, vtrCB_thunk, static_cast<void *>(this) ) == -1)
std::cout << "Error: Failure to initialize" << std::endl;
vtrimage = new vtrImage;
}
int TextDetect::vtrTest(cv::Mat imagetest)
{
/*store image data in an image structure*/
}
void TextDetect::vtrCB(vtrTextTrack *track)
{
/*send data to command line from callback */
I've tried copying the data I need a variety of ways and nothing works (this code is a continuation from above):
//texttrack = track;
//texttrack = new vtrTextTrack (*track);
memcpy(texttrack,track,sizeof(*track));
//vtrTextTrackFree(track);
}
void TextDetect::vtrCB_thunk(vtrTextTrack *track, void *calldata)
{
static_cast<TextDetect *>(calldata)->vtrCB(track);
}
This is the member function were I want the data to be used. Texttrack is public member so I might need it outside my class as well (this code is a continuation from above):
bool TextDetect::DrawBox(cv::Mat& tobeboxed)
{
And I get the access violation error at runtime here at this line of code (this code is a continuation from above):
if (texttrack->best->ocrconf > 90)
{
/*do some more stuff*/
}
}
Hopefully I'm understanding this correctly.
It seems to me that the problem is trying to copy those vtrTextTrack structs improperly.
This:
//texttrack = track;
just copies the pointer. If the owner of the struct (probably the caller of the callback function) destroys/deletes the vtrTextTrack, then you're holding on to an invalid pointer.
This one:
memcpy(texttrack,track,sizeof(*track));
will copy all the members of the vtrTextTrack, but will not copy what's being pointed to by it's member pointers (e.g. texttrack->best). Again, if the owner destroys/deletes the track, then you're holding on to invalid pointers.
And since
//texttrack = new vtrTextTrack (*track);
didn't work, I'm guessing that vtrTextTrack doesn't provide a copy constructor.
As for a workaround, first check if your third party library provides a function to copy these structs. If that's not the case (could this be by design?), then you may have to implement one yourself. This might be hard because there might be all kinds of internals that you don't know about. If you don't need the whole vtrTextTrack, I'd say define another struct and store only the information you need. Something along the lines of
SomeType* bestCopier(SomeType* src)
{
SomeType* temp;
/* copy over struct */
return temp;
}
Foo* fooCopier(Foo* src)
{
/*...*/
}
struct myTextTrack
{
public:
myTextTrack(vtrTextTrack* src)
{
//copy over stuff
m_best = bestCopier(src->best);
m_foo = fooCopier(src->foo);
}
private:
/* the members you care about*/
SomeType* m_best;
Foo * m_foo;
}