簡體   English   中英

為什么在此上下文中無法推導出模板參數?

[英]Why template argument cannot be deduced in this context?

任何人都可以解釋為什么編譯器(g ++,visual c ++)在這種情況下無法推斷模板參數?

struct MyClass
{
    void Foo(int x)&  {}
    void Foo(int x)&& {}
};

template<typename T>
void CallFoo(void(T::*func)(int)&)
{
    //create instance and call func
}

int main()
{
   CallFoo(&MyClass::Foo); // Fails to deduce T
}

為什么編譯器不能將T推導為MyClass? 這僅適用於ref限定符重載的方法。 如果方法被const-ness或參數類型重載,一切正常。 在這種情況下,似乎只有Clang才能推斷T.

總結評論中的討論:對於參考限定的成員函數作為模板參數的支持對於某些編譯器來說是一個相對較新的特性。 但是,大多數編譯器的最新版本將編譯此類代碼。


例如:

#include <iostream>

struct MyClass
{
    void Foo(int) const &
    {
        std::cout << "calling: void Foo(int) const &\n";
    }
    void Foo(int) const &&
    {
        std::cout << "calling: void Foo(int) const &&\n";
    }
};

template<typename T>
void CallFoo_lvalue(void (T::*foo)(int) const &)
{
    T temp;
    (temp.*foo)(0);
}

template<typename T>
void CallFoo_rvalue(void (T::*foo)(int) const &&)
{
    (T{}.*foo)(0);
}

int main()
{
   CallFoo_lvalue(&MyClass::Foo);
   CallFoo_rvalue(&MyClass::Foo);
}

將編譯:

產生以下輸出:

calling: void Foo(int) const &
calling: void Foo(int) const &&

對於那些想知道&&&是什么的人:這是來自@JustinTime的引用:

基本上,&是左值ref-qualifier,&&是rvalue ref-qualifier(綁定到臨時對象); 在他的例子中,MyClass m; m.Foo(3); 會調用頂部的,而MyClass {}。Foo(3); 會打電話給最底層的人。 它們作用於隱式對象參數; lvalue ref-qualifier綁定到左值引用,rvalue ref-qualifier綁定到rvalue引用(既沒有將參數作為左值引用,但讓它綁定到任何一個的函數)。 請注意,它們實際上並沒有改變*這個類型。

如果希望模板綁定到不同的引用類型,則需要使用通用引用

template<typename T>
void func(T&& arg)
{
    other_func(std::forward<T>(arg));
}

這將綁定到左值或右值引用。 std :: forward將確保在后續調用中使用適當的引用。 我不確定如何將雙&符號放入代碼中,但也許只是

template<typename T>
void CallFoo(void(T::*func)(int)&&)

也許會更好

template<typename func_t>
void CallFoo(func_t && f)
{
    call(std::forward<func_t>(f));
}

template<typename func_t>
void call(typename std::remove_reference<func_t> & f)
{
    f();
}

template<typename func_t>
void call(typename std::remove_reference<func_t> && f)
{
    f();
}

或者你需要調用函數指針的任何語法,也許* f();

如果你想傳遞參數:

template<typename func_t, typename ... args_t>
void CallFoo(func_t && f, args_t && ... args)
{
    call(std::forward<func_t>(f), std::forward<args_t>(args)...);
}

template<typename func_t, typename ... args_t>
void call(typename std::remove_reference<func_t> & f, args_t && ... args)
{
    f(std::forward<args_t>(args)...);
}

template<typename func_t, typename ... args_t>
void call(typename std::remove_reference<func_t> && f, args_t && ... args)
{
    f(std::forward<args_t>(args)...);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM