忽略候选模板:推导出参数的冲突类型:<const T&> vs <T&>

Gre*_*ape 1 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;
}
Run Code Online (Sandbox Code Playgroud)

当我传递一个lvalue,foo的说法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)
Run Code Online (Sandbox Code Playgroud)

事情是我不明白为什么会发生这种情况.可以lvalue单独传递,因为它是使用_wrapper_bar1和完成的_wrapper_bar2.而这样做不会上升这种,即任何冲突const T &VS T &.

我知道解决这个错误的方法:通过转换lvalue为rvalue使用std::move(x),但显然它不是修复,因为实际上并不需要移动.另外,有时我需要x在调用包装函数后使用,并且使用移动值是UB.

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

编辑:重载Foo::bar1()

Jar*_*d42 5

在

template <typename ...Args>
void _wrapper(void (Foo::*method) (Args ...), Args && ...args)
Run Code Online (Sandbox Code Playgroud)

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)...);
}
Run Code Online (Sandbox Code Playgroud)

实例