Проблема при проверке, если функция существует в C ++ - PullRequest
0 голосов
/ 17 ноября 2010

Я нашел очень интересный код C ++ на stackoverflow , и я очень смущен этим, потому что, как говорит автор, он должен работать, и он не работает на моих gcc 4.5.1 и 4.4 :( Цельдолжен проверить, содержит ли класс определенный метод.

код:

#include <iostream>

struct Hello
{
    int helloworld()
    { return 0; }
};

struct Generic {};


// SFINAE test
template <typename T>
class has_helloworld
{
    typedef char one;
    typedef long two;

    template <typename C> static one test( typeof(&C::helloworld) ) ;
    template <typename C> static two test(...);


public:
    enum { value = sizeof(test<T>(0)) == sizeof(char) };
};


int
main(int argc, char *argv[])
{
    std::cout << has_helloworld<Hello>::value << std::endl;
    std::cout << has_helloworld<Generic>::value << std::endl;
    return 0;
}

У меня ошибка компилятора:

ISO C ++ запрещаетинициализация в классе неконстантного статического члена 'test'

Дополнительно, как говорится в некоторых комментариях - я могу изменить 'typeof (& C :: helloworld)' на 'char [sizeof (& C :: helloworld))] 'но тогда мой вывод

1
1

что не так, потому что только один класс имеет функцию helloworld

Есть ли какой-нибудь метод, чтобы заставить его работать? Кроме того, я был бы очень благодарен, есликто-нибудь может объяснить, что именно делает эта команда:

test( char[sizeof(&C::helloworld)] ) ;

Большое спасибо:)

1 Ответ

2 голосов
/ 17 ноября 2010

Ваша проблема с использованием целого нуля и typeof.Используя MSVC10, decltype и nullptr, это тривиальная модификация для этого кода для печати правильных значений.

template <typename T>
class has_helloworld
{
    typedef char one;
    typedef long two;

    template <typename C> static one test( decltype(&C::helloworld) ) ;
    template <typename C> static two test(...);


public:
    enum { value = std::is_same<decltype(test<T>( nullptr )), char>::value };
};


int main(int argc, char *argv[])
{
    std::cout << has_helloworld<Hello>::value << std::endl;
    std::cout << has_helloworld<Generic>::value << std::endl;
    std::cin.get();
    return 0;
}

Я не эксперт по typeof, но что-то вроде этого должно быть выполнимым:

struct no_type {};
// SFINAE test
template <typename T>
class has_helloworld
{
    template <typename C> static typeof(&C::helloworld) test( C* i );
    template <typename C> static no_type test(...);


public:
    enum { value = std::is_same<no_type, typeof(test<T>(0))>::value };
};
...