non*_*741 5 c++ variadic-functions overload-resolution variadic-templates c++17
函数“Process”正在接受可变数量的变量类型参数。为了处理不同的情况,我已经成功地像这样重载了它:
// general case
template <typename ...Types>
void Process( const Types&... items )
// single T
template <typename T>
void Process( const T& t )
// one or more of type NVP<>
template <typename T1, typename ...Types>
void Process( const NVP<T1>& nvp1, const NVP<Types>&... nvps )
Run Code Online (Sandbox Code Playgroud)
我想要做的 - 但不能 - 如下:对于具有任意数量的类型的前导参数ATT<>后跟任意数量的情况,我需要重载NVP<>:
// any number of leading Types ATT<> followed by any number of NVP<>
template <typename ...ATypes, typename ...BTypes>
void Process( const ATT<ATypes>&... atts, const NVP<BTypes>&... nvps )
Run Code Online (Sandbox Code Playgroud)
起初你会认为编译器匹配它应该是“容易”的,如果它已经可以完成其他情况。这里应该绝对没有歧义!?但是,匹配失败,没有错误消息,但是编译器忽略了所需的重载。
目前使用 VS2017 和 /std:c++17
笔记:
1.它可以,很明显,被用于做一个领导型ATT<T1>这样的
// one leading Type ATT<T1>
template <typename T1, typename ...Types>
void Process( const ATT<T1>& a1, const Types&... remaining )
Run Code Online (Sandbox Code Playgroud)
但是对于不止一个,我需要做一些丑陋的手动递归。我真的很想拥有一整套领先的ATT<...>.
2.我知道一个领先的参数包——一般类型——对于匹配总是不明确的,但对于像ATT<ATypes>...不存在歧义这样的专业化。
小智 0
相信您可以使用结构来帮助您。编译器无法确定一个参数包在哪里停止而另一个参数包从哪里开始,请考虑:
foo(1, 2.0, '3', "45", 6.0f)。第一个参数包可以什么都没有,第一个,所有这些,或者以上都不是。没有特别的理由更喜欢其中一种。所以你不能创建一个接受两个变量的函数。您可以做的是将其分成两个结构,并显式指定外部类的参数。
template<typename... Args>
struct S
{
template<typename... Inner>
static void Process(const ATT<Args>&... atts, const NVP<Inner>&... nvps) {}
};
Run Code Online (Sandbox Code Playgroud)
使用示例:
ATT<double> a1;
ATT<long> a2;
NVP<int> n1;
NVP<const char*> n2;
S<double, long>::Process(a1, a2, n1, n2);
Run Code Online (Sandbox Code Playgroud)
另一个版本可以使用构造函数。在这里,您还可以获得自动扣除,这更容易。不幸的是,它仅适用于 C++17 及更高版本。
template<typename... Args>
struct S
{
std::tuple<ATT<Args>...> tup;
S(const ATT<Args>&... atts)
: tup(atts...)
{}
template<typename... Inner>
void Process(const NVP<Inner>&... nvps){}
};
template<typename... Args>
S(const ATT<Args>&... atts)->S<Args...>;
Run Code Online (Sandbox Code Playgroud)
用法是:
S(ATT(1), ATT(3.4)).Process(NVP("asdf"), NVP(3.4), NVP('f'));
return 0;
Run Code Online (Sandbox Code Playgroud)