簡體   English   中英

消除作為模板參數傳遞的重載成員函數指針的歧義

[英]Disambiguate overloaded member function pointer being passed as template parameter

我正在嘗試重新創建Observer模式 ,我可以將參數完美地轉發給觀察者的給定成員函數。

如果我嘗試傳遞具有多個覆蓋成員函數的地址,則無法根據參數推斷出正確的成員函數。

#include <iostream>
#include <vector>
#include <algorithm>

template<typename Class>
struct observer_list
{
    template<typename Ret, typename... Args, typename... UArgs>
    void call(Ret (Class::*func)(Args...), UArgs&&... args)
    {
        for (auto obj : _observers)
        {
            (obj->*func)(std::forward<UArgs>(args)...);
        }
    }
    std::vector<Class*> _observers;
};

struct foo
{
    void func(const std::string& s)
    {
        std::cout << this << ": " << s << std::endl;
    }
    void func(const double d)
    {
        std::cout << this << ": " << d << std::endl;
    }
};

int main()
{
    observer_list<foo> l;
    foo f1, f2;
    l._observers = { &f1, &f2 };

    l.call(&foo::func, "hello");
    l.call(&foo::func, 0.5);

    return 0;
}

無法使用template argument deduction/substitution failed編譯template argument deduction/substitution failed

請注意,我有Args...UArgs...因為我需要能夠傳遞參數,這些參數不一定是函數簽名的類型,但可以轉換為所述類型。

我以為我可以使用std::enable_if<std::is_convertible<Args, UArgs>>調用來消除歧義,但我不相信我可以使用可變參數模板參數包來做到這一點?

如何讓模板參數推斷在這里工作?

問題在於:

l.call(&foo::func, "hello");
l.call(&foo::func, 0.5);

對於這兩行,編譯器不知道您指的是哪個foo::func 因此,您必須通過強制轉換提供缺少的類型信息(即foo:func的類型)來消除歧義:

l.call(static_cast<void (foo::*)(const std::string&)>(&foo::func), "hello");
l.call(static_cast<void (foo::*)(const double      )>(&foo::func), 0.5);

或者,您可以提供編譯器無法推斷的模板參數,並定義func的類型:

l.call<void, const std::string&>(&foo::func, "hello");
l.call<void, double            >(&foo::func, 0.5);

請注意,您必須使用上面的double而不是const double 原因是通常doubleconst double是兩種不同的類型。 但是,有一種情況, doubleconst double被認為是相同的類型:作為函數參數。 例如,

void bar(const double);
void bar(double);

不是兩個不同的重載,但實際上是相同的功能。

暫無
暫無

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

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