gpt4 book ai didi

c++ - 带有部分参数包的可变辅助函数

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:59:30 25 4
gpt4 key购买 nike

在下面的代码中:

#include <iostream>

struct Base {
virtual ~Base() = default;
template <typename T, typename... Args> void helper (void (T::*)(Args..., int), Args...);
void bar (int n) {std::cout << "bar " << n << std::endl;}
};

struct Derived : Base {
void baz (double d, int n) {std::cout << "baz " << d << ' ' << n << std::endl;}
};

template <typename T, typename... Args>
void Base::helper (void (T::*f)(Args..., int), Args... args) {
// A bunch on lines here (hence the motivation for the helper function)
for (int n = 0; n < 5; n++)
(dynamic_cast<T*>(this)->*f)(args..., n);
// ...
}

int main() {
Base b;
Derived d;
b.helper(&Base::bar); // GCC 4.8.1 will accept this, Visual Studio 2013 won't.
d.helper<Derived, double>(&Derived::baz, 3.14); // Visual Studio 2013 will accept this, GCC 4.8.1 won't
}

我无法让 GCC4.8.1 或 VS2013 编译以上两行。他们将只编译一个而不编译另一个(而且他们也不同意哪一行是正确的和不正确的)。错误消息表明两个编译器都失败了模板推导。那么到底出了什么问题呢?我把所有的模板参数都放在最后一行(我认为这是可以推导的),但它仍然不能被 GCC 推导,尽管 VS 可以。然而,当我为其放置模板参数时,VS 无法推断出 b.foo(&Base::bar); 行的模板参数,但 GCC 可以在没有任何模板参数的情况下推断出它们。到这里完全懵了。两个编译器都在这里被窃听了吗?程序员方面是否有任何可能的修复?

最佳答案

参数包必须放在参数列表的末尾才能自动推导。

编译器无法从给定的参数列表中推导出(Args..., int),使用(int, Args...) 代替,程序将编译。

#include <iostream>

struct Base {
virtual ~Base() = default;
template <typename T, typename... Args> void helper (void (T::*)(int, Args...), Args...);
void bar (int n) {std::cout << "bar " << n << std::endl;}
};

struct Derived : Base {
void baz (int n, double d) {std::cout << "baz " << d << ' ' << n << std::endl;}
};

template <typename T, typename... Args>
void Base::helper (void (T::*f)(int, Args...), Args... args) {
// A bunch on lines here (hence the motivation for the helper function)
for (int n = 0; n < 5; n++)
(dynamic_cast<T*>(this)->*f)(n, args...);
// ...
}

int main() {
Base b;
Derived d;
b.helper(&Base::bar);
d.helper<Derived, double>(&Derived::baz, 3.14);
}

如果您必须将 int 放在参数列表的末尾,您可以使用 @Barry 所说的 identity 技巧。

准系统 identity 实现可以像这样简单:

template<typename T>
struct identity {
typedef T type;
};

然后你可以手动推断参数类型:

template <typename T, typename... Args>
void Base::helper (void (T::*f)(typename identity<Args>::type..., int), typename identity<Args>::type... args) {
// A bunch on lines here (hence the motivation for the helper function)
for (int n = 0; n < 5; n++)
(dynamic_cast<T*>(this)->*f)(args..., n);
// ...
}

b.helper<Base>(&Base::bar);
d.helper<Derived, double>(&Derived::baz, 3.14);

关于c++ - 带有部分参数包的可变辅助函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27976403/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com