C ++ Проверка, имеет ли универсальный объект функцию-член, совпадающую с сигнатурой - PullRequest
1 голос
/ 02 июня 2019

первый пост, так что надеюсь не нарушать этикета.Не стесняйтесь давать советы по улучшению вопроса.

Я видел несколько постов, похожих на этот: Проверьте, есть ли у класса функция-член с данной сигнатурой , но нетделай то, что я хочу.Конечно, он «работает с полиморфизмом» в том смысле, что он может правильно проверять типы подклассов для функции, которая приходит из суперкласса, но я хотел бы проверить сам объект, а не класс.Используя некоторый (слегка подправленный) код из этого поста:

// Somewhere in back-end
#include <type_traits>
template<typename, typename T>
struct HasFunction {
    static_assert(integral_constant<T, false>::value,
        "Second template parameter needs to be of function type."
        );
};

template<typename C, typename Ret, typename... Args>
class HasFunction<C, Ret(Args...)> {

    template<typename T>
    static constexpr auto check(T*) -> typename is_same< 
        decltype(declval<T>().myfunc(declval<Args>()...)), Ret>::type;

    template<typename>
    static constexpr false_type check(...);

    typedef decltype(check<C>(0)) type;
public:
    static constexpr bool value = type::value;
};

struct W {};
struct X : W { int myfunc(double) { return 42; } };
struct Y : X {};

Я хотел бы получить что-то вроде следующего:

// somewhere else in back-end. Called by client code and doesn't know
// what it's been passed!
template <class T>
void DoSomething(T& obj) {
    if (HasFunction<T, int(double)>::value)
        cout << "Found it!" << endl;
        // Do something with obj.myfunc
    else cout << "Nothin to see here" << endl;
}

int main()
{
    Y y;
    W* w = &y; // same object
    DoSomething(y); // Found it!
    DoSomething(*w); // Nothin to see here?
}

Проблема в том, что один и тот же объект просматривается полиморфноприводит к разным результатам (поскольку проверяемый тип - это то, что проверяется, а не объект).Так, например, если бы я перебирал коллекцию W * и вызывал DoSomething, я бы хотел, чтобы он не работал на W, но он должен что-то делать для X и Y.Это достижимо?Я все еще копаюсь в шаблонах, поэтому я все еще не совсем уверен, что возможно, но кажется, что это не так.Есть ли другой способ сделать это вообще?

Кроме того, немного меньше связано с этой конкретной проблемой: есть ли способ сделать HasFunction более похожим на интерфейс, чтобы я мог произвольно проверять различные функции?то есть не иметь ".myfunc" конкретный внутри?(кажется, что это возможно только с макросами?) Например,

template<typename T>
struct HasFoo<T> : HasFunction<T, int foo(void)> {};
int main() {
    Bar b;
    if(HasFoo<b>::value) b.foo();
}

Очевидно, что это неверный синтаксис, но, надеюсь, это поможет.

1 Ответ

0 голосов
/ 02 июня 2019

Просто невозможно выполнить глубокую проверку указателя базового класса, чтобы проверить возможные функции-члены в указанном типе (для производных типов, которые не известны заранее).Даже если мы получим отражение.

Стандарт C ++ не дает нам никакого способа выполнить этот вид проверки, потому что тип информации о типе времени выполнения, который гарантированно будет доступен, очень ограничен, в основном отнесен к type_info структура.

Ваш компилятор / платформа может предоставлять дополнительную информацию о типах времени выполнения, которую вы можете подключить, хотя точные типы и механизмы, используемые для предоставления RTTI, как правило, не документированы и их трудно исследовать ( Эта статья от Quarkslab пытается проверить иерархию RTTI MSVC)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...