- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如何附上std::is_base_of
在std::function
实际上?
我认为这是不可能的,因为类型被删除了。
如何解决?我想缓存 std::function f=check whether X derived from B
.
稍后将调用它。
#include <iostream>
#include <type_traits>
#include <functional>
using namespace std;
class B{ };
class C: B{};
int main(){
std::cout<<std::is_base_of<B,C>()<<std::endl; //print 1
std::function<bool()> f=[](X)->bool{ //<--- syntax error (X is class name)
return std::is_base_of<B,X>();
};
std::cout<<f(C)<<std::endl; //<--- possible? (should print 1)
return 0;
}
在实际情况中,f
在代码的遥远位置调用,我不想实例化 B
或 C
.
(因此,我不能使用 dynamic_cast
来检查。)
我正在尝试获取一个二维 bool 表 ( result #
) 以进行一些复杂的类型操作。
class B{};
class C : B{};
class D{};
int main(){
for(auto cachefunction : cacheFunctions){
cachefunction();
//^ "cacheFunctions" is {register<B>(), register<C>(), register<D>()}
}
//in real case, cacheFunctions.size() ~ 200+
auto result=.... //#
}
我可以编辑 register<T>()
中的代码随心所欲,但我不能要求用户调用register<T1,T2>
对于每个可能的元组。
粗略地说,result #
是 bool
的数组标记是否T2
源自 T1
.
B C D (parent)
------------
(derived)
B x 0 0
C 1 x 0
D 0 0 x (x=don't care, 0 or 1 are OK)
int[]/std::vector<int> result
= {x,0,0 , 1,x,0 , 0,0,x}
.
我的最终目标是在 //#
行获取表格.
我有一个这样调用我的库的用户代码。
这些线分散在许多用户的周围 .cpp
:-
requestSystem<S1>()->someBFunction();
requestSystem<S2>()->someCFunction();
....
Si
是我库中的子系统(在这里,我使用组合而不是继承。)。
到目前为止,我已经成功地使用了一些技巧 (array of std::function
) 来实例化那些子系统 (new Si()
),然后才在运行时实际调用这些函数。因此,它运行良好。
随着我的程序的增长,更多Si
出生。
我注意到有些情况下 Sy
最好继承自某个Sx
.
在这种情况下,我发现如果我同时实例化 new Sx()
和 new Sy()
,我的程序会表现得很奇怪,因为有两个基类实例 Sx
(它应该是单例设计)。
我认为如果我可以通过在 requestSystem<T>()
中嵌入一些额外的代码来自动检测此类情况会很好仅实例化 new S_Y()
, 让 requestSystem<S_X>()
返回指向 S_Y
的相同指针.
我不能对 array of std::function
使用同样的技巧 ( std::is_base_of
)检查继承因为类型被删除。此外,我打算不调用 new S_X()
,所以我无法通过其实例缓存类型并使用 dynamic_cast
稍后。
这是 MCVE ( ideone )。
第一部分是Manager的定义:-
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
class Manager{
public: Manager(){std::cout<<"Manager"<<std::endl; }
};
class EntityManager : public Manager{
public: EntityManager(){std::cout<<"EntityManager"<<std::endl;}
};
class AdvanceEntityManager : public EntityManager{
public: int testField=5; //just for testing
public: AdvanceEntityManager(){
std::cout<<"AdvanceEntityManager"<<std::endl;
}
};
这是类型操纵器:-
template<class T> class DummyHook{ public: static int dummyInt; };
template<class T> class IndexCache{ public: static int index; };
//^ index = index of T* inside "globalManagerList"
std::vector<Manager*> globalManagerList;
std::vector<std::function<Manager*(int)>>* getFunctionPointers(){
static std::vector<std::function<Manager*(int)>> cacher;
return &cacher;
}
/** it is called indirectly by "requestSystem" */
template<class T> int indirectCall(){
std::function<Manager*(int)> func=[](int assignIndex){
IndexCache<T>::index = assignIndex;
auto re= new T();
globalManagerList.push_back(re);
return re;
};
getFunctionPointers()->push_back(func);
int dummy=42;return dummy;
}
template<class T> T* requestSystem(){
int k=DummyHook<T>::dummyInt;
//^ optimized out, but force calling "indirectCall()" before main() at @
return static_cast<T*>(globalManagerList[IndexCache<T>::index]);
}
template<class T> int DummyHook<T>::dummyInt = indirectCall<T>(); //@
template<class T> int IndexCache<T>::index = -42;
这是主要功能:-
int main() {
auto fs=getFunctionPointers();
int n=0;
for(auto ele: *fs){
ele(n); ++n;
//^ call every function in
// static std::vector<std::function<Manager*(int)>> cacher
}
std::cout<<"All initialized, ready!"<<std::endl;
auto entityManagerPtr=requestSystem<EntityManager>();
auto advanceManagerPtr=requestSystem<AdvanceEntityManager>();
//^ In this program, they are different instance, but I want it to be the same instance.
std::cout<<"Should be 5 : "<<advanceManagerPtr->testField<<std::endl;
return 0;
}
这是输出(两个管理器都被实例化了 :(
):-
Manager
EntityManager
Manager
EntityManager
AdvanceEntityManager
All initialized, ready!
Should be 5 : 5
最佳答案
类型的基列表在运行时不可用,而这实际上是您的代码所需要的。
但是我们可以编写自己的类型系统。在这种情况下,我们用每个父项的列表标记每个类型,并在该列表上启用编译时反射。
然后我们在设置工厂的时候,也把父类型的工厂替换掉,保证只使用子类型。
这里有一些随机工具可以提供帮助:
template<class...Ts> struct types_t {};
template<class T> struct tag_t { constexpr tag_t() {} using type=T; };
template<class T> constexpr tag_t<T> tag{};
template<class Tag> using type_t=typename Tag::type;
template<std::size_t...Is>
auto index_over( std::index_sequence<Is...> ) {
return [](auto&& f)->decltype(auto) {
return decltype(f)(f)( std::integral_constant<std::size_t, Is>{}... );
};
}
template<std::size_t N>
auto index_upto( std::integral_constant<std::size_t, N> ={} ) {
return index_over( std::make_index_sequence<N>{} );
}
template<class F>
auto invoke_foreach( F&& f ) {
return [f=std::forward<F>(f)](auto&&...args){
using discard=int[];
(void)discard{0,(void(
f(decltype(args)(args))
),0)...};
};
}
template<class F>
auto invoke_on_tuple( F&& f ) {
return [f=std::forward<F>(f)](auto&& tuple)->decltype(auto) {
using Tuple = decltype(tuple);
using dTuple = std::decay_t<Tuple>;
using Size = std::tuple_size<dTuple>;
return index_upto<Size{}>()( [&](auto&&...args)->decltype(auto){
return f( std::get<decltype(args){}>( decltype(tuple)(tuple) )... );
});
};
}
template<class...Ts>
constexpr std::tuple< tag_t<Ts>... > as_tuple_tags( types_t<Ts...> ) { return std::make_tuple(tag<Ts>...); }
template<class F>
struct y_combinator_t {
F f;
template<class...Args>
decltype(auto) operator()( Args&&... args ) {
return f(*this, std::forward<Args>(args)...);
}
};
template<class F>
y_combinator_t<std::decay_t<F>> y_combinate( F&& f ) { return {std::forward<F>(f)}; }
现在,我们用他们的 parent 标记类型:
class Manager{
public: Manager(){std::cout<<"Manager"<<std::endl; }
};
class EntityManager : public Manager{
public:
int base_value = 3;
EntityManager(){std::cout<<"EntityManager"<<std::endl;}
using parents = types_t<Manager>;
};
class AdvanceEntityManager : public EntityManager{
public: int testField=5; //just for testing
public:
AdvanceEntityManager(){
std::cout<<"AdvanceEntityManager"<<std::endl;
base_value = 1;
}
using parents = types_t<EntityManager>;
};
并使用起始码让我们轻松与家长合作:
template<class T, class Parents = typename T::parents>
auto foreach_parent( tag_t<T> ) {
constexpr auto parent_tuple = as_tuple_tags( Parents() );
return [](auto&& f) {
return invoke_on_tuple(invoke_foreach(f))(decltype(parent_tuple){});
};
}
template<class T, class...Ts>
auto foreach_parent( tag_t<T>, Ts&&... ) {
return [](auto&& f) {};
}
我们设置了一个双条目缓存,一个单例工厂,并使用了智能指针:
template<class T> class IndexCache{
public:
static int index;
static int factory;
};
template<class T> class Dummy{ public: static int index; };
using pManager = std::shared_ptr<Manager>;
using ManagerFactory = std::function<pManager()>;
using Task = std::function<void()>;
std::vector<pManager> globalManagerList;
std::vector<Task>& getManagerFactories(){
static std::vector<Task> cacher{};
return cacher;
}
template<class T>
ManagerFactory singleton_factory() {
return []{
static auto single = (void(std::cout << "making " << typeid(T).name() << " singlton" << std::endl), std::make_shared<T>());
return single;
};
}
并修改间接调用以替换父工厂任务:
template<class T>
void indirectCall(){
std::cout << "Setting up " << typeid(T).name() << std::endl;
auto func=[](auto tag){
return [tag](){
IndexCache<type_t<decltype(tag)>>::index = globalManagerList.size();
globalManagerList.push_back(singleton_factory<T>()());
};
};
//std::cout << "Adding " << typeid(T).name() << " factory " << std::endl;
IndexCache<T>::factory = getManagerFactories().size();
getManagerFactories().push_back(func(tag<T>));
auto replace_parents = y_combinate(
[&](auto& replace_parents, auto child_tag) {
foreach_parent(child_tag)([&](auto parent_tag){
using Parent = type_t<decltype(parent_tag)>;
std::cout << "Replacing " << typeid(Parent).name() << " factory with " << typeid(T).name() << " factory" << std::endl;
getManagerFactories()[IndexCache<Parent>::factory] = func(tag<Parent>);
replace_parents( parent_tag );
});
}
);
replace_parents(tag<T>);
std::cout << "Added " << typeid(T).name() << " factory " << std::endl;
}
在 requestSystem
中,我们确保所有设置都已完成:
void setup_code() {
for (auto&& factory:getManagerFactories())
factory();
}
void setup() {
static int unused = (setup_code(),7);
(void)unused;
}
template<class T>
T* requestSystem()
{
int dummy = Dummy<T>::index;
(void)dummy;
std::cout << "Requesting " << typeid(T).name() << std::endl;
setup();
return static_cast<T*>(globalManagerList[IndexCache<T>::index].get());
}
template<class T> int IndexCache<T>::index = -1;
template<class T> int IndexCache<T>::factory = -1;
template<class T> int Dummy<T>::index = (indirectCall<T>(), 7);
然后我们测试它:
int main() {
std::cout<<"All initialized, ready!"<<std::endl;
auto entityManagerPtr=requestSystem<EntityManager>();
//std::cout<<"Phase 1"<<std::endl;
(void)entityManagerPtr;
auto advanceManagerPtr=requestSystem<AdvanceEntityManager>();
//std::cout<<"Phase 2"<<std::endl;
//^ In this program, they are different instance, but I want it to be the same instance.
std::cout<<"Should be 5 : "<<advanceManagerPtr->testField<<std::endl;
std::cout<<"Should be 1 : "<<entityManagerPtr->base_value<<std::endl;
return 0;
}
这里我们请求entityManagerPtr
,我们得到了advanceManagerPtr
。从日志中可以看出,只创建了一个对象,其entityManagerPtr->base_value为1。
关于c++ - std::function 检查类的继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43168297/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!