具有函数参数评估的 C++17 参数包扩展
C++17 parameter pack expansion with function parameter evaluation
我正在研究可变参数模板和折叠表达式,特别是进行类型转换以放入函数参数中。我的理解是做类似的事情:
template<T, typename ... Args>
void convertAndEvaluate(const vector<T>& convertibles)
{
size_t i = 0;
evaluate(some_function<Args>(convertibles[i++])...);
}
将不起作用,因为未指定函数输入的评估顺序。折叠表达式可以给出正确的求值顺序,但是它们的结果是用括号括起来的,不能用作函数输入。我可以通过另一个模板函数使用 index_sequences 实现相同的结果,但我想知道 C++17 是否有更简洁的方法,比如使用 constexpr 和 pack扩张.
玩具示例:
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
template<typename ... Args>
class Foo {
public:
Foo() {}
void just_print(const std::vector<int>& convertible)
{
size_t i = 0;
((cout << static_cast<Args>(convertible[i++]) << " "), ...);
cout << endl;
}
template<typename T,T... ints>
void expandEvaluate(const std::vector<int>& values, std::integer_sequence<T, ints...> int_seq)
{
eval(static_cast<Args>(values[ints])...);
}
void convert(const std::vector<int>& convertible)
{
expandEvaluate(convertible, std::make_index_sequence<sizeof...(Args)>());
}
void convert_wrong(const std::vector<int>& convertible)
{
size_t i = 0;
eval(static_cast<Args>(convertible[i++])...);
}
void eval(const Args&... values)
{
((cout << values << " "), ...);
cout << endl;
}
};
int main()
{
Foo<double, int, float, int, double> bar;
bar.eval(3, 4, 5, 6, 7);
bar.just_print({3, 4, 5, 6, 7});
bar.convert_wrong({3, 4, 5, 6, 7});
bar.convert({3, 4, 5, 6, 7});
return 0;
}
输出:
3 4 5 6 7
3 4 5 6 7
7 6 5 4 3
3 4 5 6 7
编辑:
回想起来,我的整数扩展的解决方案需要同时扩展两个参数包,这是标准中定义的吗?
我认为您的解决方案(使用 std::make_index_sequence
/std::index_sequence
以正确的顺序获取索引)是一个很好的解决方案(也适用于 C++14)。
从 C++17 开始,您还可以使用 std::tuple
/std::apply()
void convert2 (std::vector<int> const & cv)
{
std::size_t i{};
std::tuple t{ static_cast<Args>(cv[i++])... };
std::apply([=](auto ... args){ eval(args...); }, t);
}
但这几乎是您的 std::make_index_sequence
/std::index_sequence
解决方案,由 std::apply()
包装。
我正在研究可变参数模板和折叠表达式,特别是进行类型转换以放入函数参数中。我的理解是做类似的事情:
template<T, typename ... Args>
void convertAndEvaluate(const vector<T>& convertibles)
{
size_t i = 0;
evaluate(some_function<Args>(convertibles[i++])...);
}
将不起作用,因为未指定函数输入的评估顺序。折叠表达式可以给出正确的求值顺序,但是它们的结果是用括号括起来的,不能用作函数输入。我可以通过另一个模板函数使用 index_sequences 实现相同的结果,但我想知道 C++17 是否有更简洁的方法,比如使用 constexpr 和 pack扩张.
玩具示例:
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
template<typename ... Args>
class Foo {
public:
Foo() {}
void just_print(const std::vector<int>& convertible)
{
size_t i = 0;
((cout << static_cast<Args>(convertible[i++]) << " "), ...);
cout << endl;
}
template<typename T,T... ints>
void expandEvaluate(const std::vector<int>& values, std::integer_sequence<T, ints...> int_seq)
{
eval(static_cast<Args>(values[ints])...);
}
void convert(const std::vector<int>& convertible)
{
expandEvaluate(convertible, std::make_index_sequence<sizeof...(Args)>());
}
void convert_wrong(const std::vector<int>& convertible)
{
size_t i = 0;
eval(static_cast<Args>(convertible[i++])...);
}
void eval(const Args&... values)
{
((cout << values << " "), ...);
cout << endl;
}
};
int main()
{
Foo<double, int, float, int, double> bar;
bar.eval(3, 4, 5, 6, 7);
bar.just_print({3, 4, 5, 6, 7});
bar.convert_wrong({3, 4, 5, 6, 7});
bar.convert({3, 4, 5, 6, 7});
return 0;
}
输出:
3 4 5 6 7
3 4 5 6 7
7 6 5 4 3
3 4 5 6 7
编辑: 回想起来,我的整数扩展的解决方案需要同时扩展两个参数包,这是标准中定义的吗?
我认为您的解决方案(使用 std::make_index_sequence
/std::index_sequence
以正确的顺序获取索引)是一个很好的解决方案(也适用于 C++14)。
从 C++17 开始,您还可以使用 std::tuple
/std::apply()
void convert2 (std::vector<int> const & cv)
{
std::size_t i{};
std::tuple t{ static_cast<Args>(cv[i++])... };
std::apply([=](auto ... args){ eval(args...); }, t);
}
但这几乎是您的 std::make_index_sequence
/std::index_sequence
解决方案,由 std::apply()
包装。