【问题标题】:Why doesn't my template parameter pack work?为什么我的模板参数包不起作用?
【发布时间】:2015-11-17 02:52:08
【问题描述】:

我一直在尝试获取一个模板函数来调用一组类似的函数以避免样板。

FooA(float a, Widget* w);
FooB(int b, Widget* w);
FooC(int c, Widget* w);
FooD(int d, int e, Widget* w);

template <typename... Args>
static void RunFoo(void (*foo)(Args..., Widget*), Args... args) {
    Widget w
    foo(args, &w);
}

我不明白为什么这适用于:

float a = 10;
RunFoo(FooA, a);

但每当我尝试使用多个参数时它都会失败:

int a = 10;
int b = 3;
RunFoo(FooD, a, b);

编译失败,报错: "候选模板被忽略:模板参数推导失败"

这超出了 c++ 模板的能力吗?

【问题讨论】:

    标签: c++ templates c++11 template-argument-deduction


    【解决方案1】:
    template<class T>struct tag {using type=T;};
    template<class Tag>using type_t=typename Tag::type;
    template<class T>using block_deduction=type_t<tag<T>>;
    
    template <typename... Args>
    static void RunFoo(block_deduction<void(*)(Args...,Widget*)> foo, Args... args) {
      Widget w
      foo(args, &w);
    }
    

    你不能像Args..., Widget*那样推断——参数包通常必须在最后。

    这两种情况在扣除上是“相等的”。 block_deduction 防止对该参数进行扣除。所以另一个推论发生了,并且有效。

    请注意,这样的扣除通常是一个坏主意。您不想推导出一个参数,并在其他地方生成一个函数指针。它很脆。

    这可能会更好:

    template <class F, class... Args>
    static std::result_of_t<F(Args..., Widget*)> RunFoo(F&& f, Args&&... args) {
      Widget w
      return std::forward<F>(f)(std::forward<Args>(args)..., &w);
    }
    

    如果您要传入一个重载集,请将重载集包装在一个重载集对象中。 std::result_of_t&lt;?&gt; 是 C++14,在 C++11 中替换为 typename std::result_of&lt;?&gt;::type

    【讨论】:

      猜你喜欢
      • 2015-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      • 2021-12-06
      相关资源
      最近更新 更多