gpt4 book ai didi

c++ - 模板类成员?由于没有任何行为,如何适本地实现这种行为?

转载 作者:太空宇宙 更新时间:2023-11-04 11:54:49 24 4
gpt4 key购买 nike

class EG
{
template<class T>
std::function<void(T)> f;

//these are supposed to be appropriate instantiations that I have to look up how to do as I haven't really used templates
template<std::string> f;
template<int> f;

template<class T>
void func(std::function<void(T)>&& arg)
{
f<std::string> = nullptr;
f<int> = nullptr;
f.swap(arg);
}

};

这是我要做的。

EG eg;
eg.func([](std::string s){});
eg.func([](int i){});

有一个回调缓存 (f),它可以接受不同的参数(指向对象的指针、位置 vector 等)。它用于模拟程序中的鼠标定位。当我开始另一个目标进程时,我需要取消当前目标(这意味着现在 f = null)。我只是不想要很多实际上做同样事情的函数和成员(但对于不同的参数)。我该如何解决这个问题?

我可以简单地检查是否有一个带有 bool 而不是 f == null 的目标,但我仍然需要多个 f 实例用于不同的回调参数)。使用 bool 而不是 f == nullptr 检查将阻止我拥有模板化类。检查 f == nullptr 是否也会阻止我拥有模板化类。

更多案例信息:

这实际上是一个回调处理程序,T 只有两种不同的类型在使用(当前)。

我试图防止它们有多个 f1、f2... 和 void func 变体。

最佳答案

评论有点长,所以我将其作为答案发布:

class EG
{
template<class T>
std::function<void(T)> f; // a data member template?

template<class T>
void func(std::function<void(T)>&& arg)
{
f = nullptr;
f.swap(arg);
// could as well just
// f = std::move(arg);
}
};

如果您的用例是:

EG obj;

obj.func( [](int i) { std::cout << i; } );
obj.f(42);

obj.func( [](string s) { std::cout << s; } );
obj.f("hello world");

这很容易出错,因为编译器无法检查函数调用 obj.f 的参数类型,因为参数类型应该是可变的:如果你分配一个 void(int) 通过 obj.func,它应该接受一个 int;如果你分配一个 void(string) 比它应该接受一个字符串。

C++ 中没有数据成员模板(IMO 拥有它们没有意义 - 它们应该何时被实例化?),但可以获得上述用例的行为。


一个 更简单、不易出错 的解决方案:

#include <functional>
#include <string>
#include <iostream>
#include <memory>

using std::string;

struct any_function
{
virtual ~any_function()
{}
};
template < typename T >
struct concrete_function
: public any_function
{
T m;
concrete_function(T&& p)
: m( std::move(p) )
{}
virtual ~concrete_function() override
{}
};

struct EG
{
private:
std::shared_ptr<any_function> fs;

public:
EG& operator=(std::function<void(int)>&& p) // do NOT templatize this!!!!
{
using stor_type = concrete_function< std::function<void(int)> >;
fs = std::make_shared<stor_type>( std::move(p) );
return *this;
}
EG& operator=(std::function<void(string)>&& p) // do NOT templatize this!!!!
{
using stor_type = concrete_function< std::function<void(string)> >;
fs = std::make_shared<stor_type>( std::move(p) );
return *this;
}

void operator()(int p) // do NOT templatize this!!!!
{
using stor_type = concrete_function< std::function<void(int)> >;
auto const& ptr = std::static_pointer_cast< stor_type >(fs);
if(ptr) { ptr->m(p); }
else { /* throw something */ }
}
void operator()(string p) // do NOT templatize this!!!!
{
using stor_type = concrete_function< std::function<void(string)> >;
auto const& ptr = std::static_pointer_cast< stor_type >(fs);
if(ptr) { ptr->m(p); }
else { /* throw something */ }
}
};


int main()
{
EG obj;

obj = [](int i) { std::cout << i; };
obj(42); // using overload mechanism
}

您不应该将标记的函数模板化,因为创建时使用的类型 (make_shared) 必须完全匹配调用中使用的类型 (static_pointer_cast )。

或者,使用枚举:

#include <functional>
#include <string>
#include <iostream>

using std::string;

struct EG
{
enum stored_function_type
{
INT_FUNC, STRING_FUNC
};

union function_storage
{
std::function<void(int)> f_int;
std::function<void(string)> f_string;

function_storage()
: f_int()
{}
~function_storage()
{}
};

stored_function_type ft;
function_storage fs;

template < typename T > void destroy(T& p) { p.~T(); }
void destroy()
{
switch(ft)
{
case INT_FUNC:
destroy(fs.f_int);
break;
case STRING_FUNC:
destroy(fs.f_string);
break;
}
}

EG()
: ft(INT_FUNC)
{}
~EG()
{
destroy();
}

EG& operator=(std::function<void(int)>&& p)
{
destroy();
new(&fs.f_int) std::function<void(int)>( std::move(p) );
ft = INT_FUNC;

return *this;
}
EG& operator=(std::function<void(string)>&& p)
{
destroy();
new(&fs.f_string) std::function<void(string)>( std::move(p) );
ft = STRING_FUNC;

return *this;
}

void operator()(int p)
{
// better check ft == INT_FUNC
return fs.f_int(p);
}
void operator()(string p)
{
// better check ft == STRING_FUNC
return fs.f_string(p);
}
};


int main()
{
EG obj;

obj = [](int i) { std::cout << i; };
obj(42); // using overload mechanism
}

您可以使用精美的模板元编程为许多类型简化这一过程。

免责声明:自从我使用 unions 以来已经有很长一段时间了……可能会遗漏一些东西。

关于c++ - 模板类成员?由于没有任何行为,如何适本地实现这种行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16571818/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com