Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将函数应用于元组中的每个元素,将每个元素强制转换为类型包中的不同类型,然后作为参数包传递_C++_Templates_C++17_Variadic Functions - Fatal编程技术网

C++ 将函数应用于元组中的每个元素,将每个元素强制转换为类型包中的不同类型,然后作为参数包传递

C++ 将函数应用于元组中的每个元素,将每个元素强制转换为类型包中的不同类型,然后作为参数包传递,c++,templates,c++17,variadic-functions,C++,Templates,C++17,Variadic Functions,我正在构建一个复杂的可扩展系统。细节并不重要,但我真的很喜欢这个设计,除了这个问题 对于某些类型的T,我有一个带有state:Subject的接口 有问题的类是在模板上模板化的 它包含一个std::tuple> 我有一个函数std::any getStateFor(std::shared_ptr)(其中WithState:Subject) 我还有一个函数void handleStates(StateTypes…states)(此时不妨使用一个元组,只要更简单) 现在我需要将所有这些部分插在一起:

我正在构建一个复杂的可扩展系统。细节并不重要,但我真的很喜欢这个设计,除了这个问题

对于某些类型的T,我有一个带有state:Subject的接口

有问题的类是在
模板
上模板化的

它包含一个
std::tuple>

我有一个函数
std::any getStateFor(std::shared_ptr)
(其中
WithState:Subject

我还有一个函数
void handleStates(StateTypes…states)
(此时不妨使用一个元组,只要更简单)

现在我需要将所有这些部分插在一起:我需要将元组中的元素向上转换为
shared\u ptr
,然后按顺序将
getStateFor
应用于这些元素中的每个元素,并按
StateTypes…
的顺序对结果进行转换,然后将所有这些作为参数包一次转发到
handleStates

(在这之前被标记为XY问题:更高级别的抽象不关心具体的状态类型,而我希望实现具有尽可能多的类型安全性的较低部分。到目前为止,这种方法看起来很适合我的需要)

我可能可以通过将我的元组转换为向量来实现这一点,在每个元组上应用
getStateFor
,然后编写一个递归函数来应用适当的
any\u cast
,但是我仍然不知道如何将结果收集到不同类型的元组中。我想知道这是否适用于智能折叠表达式

以下是现有代码的框架:

#包括
#包括
#包括

但是,这仍然缺少对具体类型的
std::any_cast
s


有什么想法吗?

主要问题是元组包含
std::shared\u ptr…
,因此
apply
将尝试使用调用给定的lambda,但lambda只接受
StateTypes&&…

为了让它工作,还有一些变化,但首先是工作:

  • 我将
    getStateFor
    更改为一个模板函数,您可以在其中指定所需的类型:

    template<class StateType>
    StateType getStateFor(std::shared_ptr<Subject> s)
    {
        if (auto withState = std::dynamic_pointer_cast<WithState<StateType>>(s))
            return withState->getValue();
        throw "AHHH";
    }
    
  • std::shared_ptr
    转到
    std::shared_ptr
    也不需要
    dynamic_指针\u cast

  • 您的元组类型有一个额外的


编辑:使用更新问题中的代码段,您可以得到以下结果:

同样的考虑仍然适用,您只需在其中添加一个
any\u cast

void handleStatesForSubjects(std::function<std::any(std::shared_ptr<Subject>)> getStateFor)
{
  std::apply(
    [this, getStateFor](std::shared_ptr<WithState<StateTypes>>... withStates) {
      handleStates(std::any_cast<StateTypes>(getStateFor(withStates))...);
    },
    subjects
  );
}
void handleStatesForSubjects(std::function getStateFor)
{
标准::应用(
[this,getStateFor](std::shared_ptr…with states){
HandleState(标准::任意类型(getStateFor(withStates))…);
},
学科
);
}

它可能比您预期的更简单,但您只需写下每个元素的操作:调用
getStateFor
,然后调用
any\u cast
。对每个可变参数重复(
)。您不需要任何
dynamic\u pointer\u cast
或类似的-
std::shared\u ptr
可以隐式转换为
std::shared\u ptr

,如果您提供了相关类型的框架,我们将更容易使用它。目前,任何想回答这个问题的人都必须手工制作。我们都是程序员,所以如果您想交流代码的功能,只需显示代码即可。不要试图解释它。“我需要将元组中的元素向上转换为shared_ptr,然后按顺序将getStateFor应用于这些元素中的每一个,然后按StateTypes的顺序将结果转换为std::any_…,然后将所有这些作为参数包一次转发给handleStates。”为什么需要使用迂回的方法来实现这一点?如果您有
StateTypes
,那么您就知道这些东西包含哪些类型。那么为什么要转换为基类呢?如果它们已转换为基类,为什么不将它们转换回具有
StateTypes
的派生类呢?当你知道这些类型时,为什么要使用这种
任何
方法呢?@nicolasbolas我添加了一个代码框架,这可能会有所帮助。关键是我从一个更高、更动态的抽象级别获得了
handleState
函数(这也是从另一个级别的较低级别获得的)。整个设计需要一篇论文,我还没有写。但是C#中一个更简单的版本在生产环境中工作,所以我知道我走在了正确的轨道上
b
之后缺少分号。我建议(或其他在线编译器)快速检查代码是否已编译。任何试图回答此问题的人都可能会将其粘贴到其中作为第一步,因此如果没有错误,您的问题将有一个良好的开端。@MaxLanghof感谢您的提示,我编辑了代码并添加了一个godbolt链接。遗憾的是,
getStateFor
来自更高级别的抽象,它动态地管理许多具有部分重叠类型的
StateHandler
s。所以我不能给它做模板。我仍然很感激你对我的方法的见解。@Dracam从我所知道的情况来看,这不应该是个问题。这只是一个更无意义的铸造。正在将此应用于您的代码示例。@Dracam我仍然对
std::any
持怀疑态度,但我想它不会比
std::dynamic\u pointer\u cast
更昂贵(这就是
std::any
最初的工作原理,这就是为什么这是一个奇怪的组合)。请注意,孤立地说,这个问题可以在没有任何
std::any
、common
Subject
基类或其他形式的类型擦除的情况下解决(因此,如果相关的话,性能会好得多):注意:类型和值扩展的混合是有效的,因为您详细说明了lambda的参数列表(你不再推断了)
void handleStatesForSubjects(std::function<std::any(std::shared_ptr<Subject>)> getStateFor)
{
  std::apply(
    [this, getStateFor](std::shared_ptr<WithState<StateTypes>>... withStates) {
      handleStates(std::any_cast<StateTypes>(getStateFor(withStates))...);
    },
    subjects
  );
}