Есть ли способ определить, существует ли функция и может ли она использоваться во время компиляции?

Редактировать: Краткий ответ на мой вопрос заключается в том, что у меня было ошибочное представление о том, что может делать SFINAE, и он вообще не проверяет тело функции: создает ли sfinae экземпляры тело функции?

У меня проблема, похожая на эту: Можно ли написать шаблон для проверки существования функции?

Разница в том, что я хочу не только проверить, существует ли функция, но и узнать, действительно ли она пройдет SFINAE. Вот пример того, что я пытаюсь сделать:

struct A
{
    void FuncA() { std::cout << "A::FuncA" << std::endl; }
};

struct B
{
    void FuncA() { std::cout << "B::FuncA" << std::endl; }
    void FuncB() { std::cout << "B::FuncB" << std::endl; }
};

template
struct Inter
{
    void FuncA() { t.FuncA(); }
    void FuncB() { t.FuncB(); }

    T t;
};

// Always takes some sort of Inter.
template
struct Final
{
    void CallFuncs()
    {
        // if( t.FuncA() exists and can be called )
            t.FuncA();

        // if( t.FuncB() exists and can be called )
            t.FuncB();
    }

    InterType t;
};

void DoEverything()
{
    Final> finalA;
    Final> finalB;

    finalA.CallFuncs();
    finalB.CallFuncs();
}

Обратите внимание, что в CallFuncs() всегда будут существовать и FuncA(), и FuncB(), но они могут не компилироваться в зависимости от типа T, используемого в Inter.Когда я пытался использовать ответ в приведенном выше связанном вопросе, он, казалось, всегда давал мне истину, и я предполагаю, что это только проверка того, что функция существует, а не то, что она действительно может быть скомпилирована (хотя я не могу исключить, что Я ничего не напутал...)

Для условного вызова функций, как я полагаю, я могу использовать enable_if как таковой:

template
typename std::enable_if< ! /* how to determine if FuncA can be called? */>::type TryCallFuncA( InterType& i )
{
}
template
typename std::enable_if::type TryCallFuncA( InterType& i )
{
    i.FuncA();
}

template
typename std::enable_if< ! /* how to determine if FuncB can be called? */>::type TryCallFuncB( InterType& i )
{
}
template
typename std::enable_if::type TryCallFuncB( InterType& i )
{
    i.FuncB();
}

template
struct Final
{
    void CallFuncs()
    {
        TryCallFuncA(t);
        TryCallFuncB(t);
    }

    InterType t;
};

но я не уверен, есть ли способ получить логическое значение для перейти в enable_if. Есть ли способ, которым я могу это сделать, или мне нужно вернуться к каким-то поддерживаемым вручную признакам типа, которые указывают, существуют ли функции?

Что касается доступного набора функций C++11, я использую MSVC 2010.

edit: Чтобы добавить важное примечание, в моей реальной ситуации реализация класса Inter является фактически непрозрачным в точке, где мне нужно определить, будет ли компилироваться Inter::FuncA/FuncB, поэтому я не могу просто всплывать дочерние типы и проверять наличие функции для них.

6
задан Community 23 May 2017 в 12:25
поделиться