标签: pack-expansion

参数包扩展中的求值顺序问题

我写了一个模板,它接受一个istream&和一个函数,应该从 中提取这个函数的所有参数,istream用这些参数调用函数并返回结果。一切正常,除了函数参数的评估顺序。请参阅下面的代码、更多详细信息和最终问题:

#include <iostream>
#include <vector>

void Foo(int i, std::string s)
{
    std::cout << "input was " << i << " and " << s << '\n';
}

template<typename T>
T Parse(std::istream &s)
{
    T res;
    
    s >> res;
    
    return res;
}

template<typename TR, typename ... TArgs>
TR Bar(std::istream &s, TR f(TArgs...) )
{
    return f(Parse<TArgs>(s)...);
}

int main()
{
    Bar(std::cin, Foo);
}
Run Code Online (Sandbox Code Playgroud)

输入:

1 2
Run Code Online (Sandbox Code Playgroud)

预期输出:

input was 1 and 2
Run Code Online (Sandbox Code Playgroud)

实际输出:

input was 2 …
Run Code Online (Sandbox Code Playgroud)

c++ pack-expansion parameter-pack

21
推荐指数
1
解决办法
504
查看次数

如何创建具有可变数量的类型参数的模板?

在我们的代码库中,我们经常使用std::variant<std::shared_ptr<SomeClass>, ...>

显然,这需要大量的写作。如何制作模板?

template <class... T>
using VarSP = std::variant<std::shared_ptr<???>>;
Run Code Online (Sandbox Code Playgroud)

T以上代码片段应该放在哪里?所需的行为应为:

VarSP<Foo, Bar, Baz> // std::variant<std::shared_ptr<Foo>, std::shared_ptr<Bar>, std::shared_ptr<Baz>>
Run Code Online (Sandbox Code Playgroud)

c++ variadic-templates pack-expansion

8
推荐指数
1
解决办法
196
查看次数

Black Magic 使用 Initializer_list 和包扩展

为了扩展灵活的函数参数,有一种方法使用std::initializer_list. 然而我无法理解。任何人都可以以可以理解的方式解释这一点吗?

template<typename T, typename... Args>
auto print(T value, Args... args) {
    std::cout << value << std::endl;
    return std::initializer_list<T>{([&] {
        std::cout << args << std::endl;
    }(), value)...};
}
Run Code Online (Sandbox Code Playgroud)

c++ variadic-templates c++14 pack-expansion

6
推荐指数
1
解决办法
108
查看次数

函数模板重载解析期间的 MSVC 与 Clang/GCC 错误,其中一个函数模板包含参数包

当我使用参数包时,我注意到这样一种情况(如下所示)在 gcc 和 clang 中编译得很好,但在 msvc 中却不行:

template<class T> void func(T a, T b= T{})
{
    
}
template<class T, class... S> void func(T a, S... b)
{

}
 
int main()
{
    func(1); // Should this call succeed? 
}
Run Code Online (Sandbox Code Playgroud)

这是验证相同内容的链接:https://godbolt.org/z/8KsrcnMez

可以看到,上面的程序在 msvc 中失败,并显示错误消息:

<source>(13): error C2668: 'func': ambiguous call to overloaded function
<source>(6): note: could be 'void func<int,>(T)'
        with
        [
            T=int
        ]
<source>(2): note: or       'void func<int>(T,T)'
        with
        [
            T=int
        ]
<source>(13): note: while trying to match the argument list …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer function-templates pack-expansion parameter-pack

5
推荐指数
1
解决办法
226
查看次数

试图要求多个可变参数类型为特定类型

目前这是伪代码,因为这是我在开始将其编写为完整代码之前正在研究的想法。

我知道我可以创建一个正常的可变参数函数使用va_argva_listprintf()确实,但是,我想完全避免使用它们。

我正在考虑使用模板可变参数来代替。我正在考虑使用可变参数制作一个可实例化的类模板。这里的条件是这个类的构造函数只能接受两种类型,但两种类型的数量可以不同。我知道,与编译器的解释方式和调用顺序相比,代码中参数的写入位置是不可知的,但这不是问题。我为参数选择的顺序是出于可读性和一致性目的的约定。

这是伪代码的示例:

class TypeIn {...}
class TypeOut{...}

template<typename... T1, typename... T2>
class MyObject {
    std::array<TypeIn*> inputs_;
    std::array<TypeOut*> outputs_;
public:
    MyObject(T1&&... inputs, T2&& ... outputs) { ... }
};
Run Code Online (Sandbox Code Playgroud)

因为我仍然在C ++ 17的工作,并没有C ++ 20的概念,模块和协程,只是还没有,这将是最干净最可靠和最有效的方式,以确保T1TypeInT2是一TypeOut类对象并相应地填充数组?我可以使用向量,但是一旦对象被构造,输入和输出的大小就不会改变。

可能的用例是:

using In = TypeIn;
using Out = TypeOut;
MyObject obj( In a, In b, In c, Out x, Out y);
Run Code Online (Sandbox Code Playgroud)

如果可能的话,我宁愿不使用这个语法:

MyObject<In,In,In,Out,Out> obj( In a, In b, In c, Out …
Run Code Online (Sandbox Code Playgroud)

c++ types variadic-templates c++17 pack-expansion

0
推荐指数
1
解决办法
89
查看次数