c++ через Disambiguate перегруженный указатель функции участника передается как параметр шаблона



указатели и ссылки c++ (1)

Проблема здесь:

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

Для обеих строк компилятор не знает, к какой foo::func вы обращаетесь. Следовательно, вы должны устранить себя, предоставив информацию о типе, которая отсутствует (т. 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 и not const double выше. Причина в том, что обычно double и const double являются двумя разными типами. Однако есть одна ситуация, когда double и const double считаются так, как если бы они были одного типа: как аргументы функции. Например,

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

не являются двумя разными перегрузками, но на самом деле являются одной и той же функцией.

Я пытаюсь воссоздать шаблон 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 .

Обратите внимание, что у меня были Args... и UArgs... потому что мне нужно иметь возможность передавать параметры, которые не обязательно являются одним и тем же типом типа типа сигнатуры функции, но могут быть конвертированы в указанный тип.

Я думал, что могу использовать вызов std::enable_if<std::is_convertible<Args, UArgs>> для устранения неоднозначности, но я не верю, что могу сделать это с помощью пакета параметров вариационного шаблона?

Как я могу заставить вывод аргумента шаблона работать здесь?





typetraits