忽略候选模板:推导出参数的冲突类型:<const t =“”&=“”> vs <t&=“”> </t> </const>

时间:2015-03-31 11:21:50

标签: c++ templates c++11

我的类中有一个成员函数_wrapper,它封装了一些围绕其他函数族的常见逻辑。此包装函数接受指向正在包装的函数及其参数的指针。

我的类中的包装器实现类似于此示例类Foo中的方式:

#include <functional>

class Foo
{
public:
    void bar1(int a)
    {
        /// No-op.
    }

    void bar1(int a, int b)
    {
        /// No-op.
    }

    void bar2(const int & a)
    {
        /// No-op.
    }

    void foo(int x)
    {
        _wrapper_bar1(x);           /// No problems to deduce type
        _wrapper_bar2(x);           /// No problems to deduce type

        _wrapper(&Foo::bar1, x);    /// Deduction fails
        _wrapper(&Foo::bar2, x);    /// Deduction fails
    }

private:
    template <typename ...Args>
    void _wrapper(void (Foo::*method) (Args ...), Args && ...args)
    {
        /// Do some common stuff here...

        (this->*method)(std::forward<Args>(args)...);
    }

    template <typename ...Args>
    void _wrapper_bar1(Args && ...args)
    {
        bar1(std::forward<Args>(args)...);
    }

    template <typename ...Args>
    void _wrapper_bar2(Args && ...args)
    {
        bar2(std::forward<Args>(args)...);
    }
};

int main(int argc, char ** argv)
{
    Foo().foo(123);
    return 0;
}

当我将lvaluefoo的参数int x传递给包装器时,clang编译器抱怨冲突和演绎失败:

test.cpp:21:9: error: no matching member function for call to '_wrapper'
        _wrapper(&Foo::bar1, x);    /// Deduction fails
        ^~~~~~~~
test.cpp:27:10: note: candidate template ignored: deduced conflicting types for parameter 'Args' (<int> vs. <int &>)
    void _wrapper(void (Foo::*method) (Args ...), Args && ...args)
         ^
test.cpp:22:9: error: no matching member function for call to '_wrapper'
        _wrapper(&Foo::bar2, x);    /// Deduction fails
        ^~~~~~~~
test.cpp:27:10: note: candidate template ignored: deduced conflicting types for parameter 'Args' (<const int &> vs. <int &>)
    void _wrapper(void (Foo::*method) (Args ...), Args && ...args)

事情是我不明白为什么会这样。可以单独传递lvalue,因为它是使用_wrapper_bar1_wrapper_bar2完成的。这样做不会引起任何此类冲突,即const T & vs T &

我知道解决此错误的方法:使用lvaluervalue投射到std::move(x),但显然不是修复,因为实际上并不需要移动。此外,有时我需要在调用包装函数后使用x,并且使用移动的值是UB。

可能我的模板非常破碎,我遗漏了一些明显的东西。我很感激你的帮助。

修改重载Foo::bar1()

1 个答案:

答案 0 :(得分:5)

template <typename ...Args>
void _wrapper(void (Foo::*method) (Args ...), Args && ...args)

Args可以从2个地方推断出来。

您可以通过引入其他模板参数来解决这个问题:

template <typename ...Args, typename ...Arg2s>
void _wrapper(void (Foo::*method) (Args ...), Arg2s&& ...args)
{
    /// Do some common stuff here...

    (this->*method)(std::forward<Arg2s>(args)...);
}

Live example