Как стать автором
Обновить

Комментарии 14

НЛО прилетело и опубликовало эту надпись здесь
Не за что :)

Вообще, идея использовать SFINAE для таких вещей из boost::mpl (там есть подобный макрос, который позволяет определить наличие типа с именем X внутри класса). Это некое обобщение, которое позволяет проверять не только типа, а практически все, что пожелает душа :)
Вот в такие моменты особенно D :)
Но красиво, да.
Слово пропустили, но таки да. В такие моменты особенно D
И вовсе ничего я не пропускал.
D здесь — наречие :)
НЛО прилетело и опубликовало эту надпись здесь
Как я уже писал выше, has_xxx не позволяет проверять что угодно, конкретно boost::mpl умеет:
1. Проверять наличие типа с именем XXX внутри класса
2. Проверять наличие шаблонного типа template<… > class XXX внутри класса.

Оба примера, которые есть в посте (проверка наличия функции f()) и проверка, на возможность ввода/вывода через потоки не реализуемы на бусте.
НЛО прилетело и опубликовало эту надпись здесь
прошу прощения, не writeonly ли..? :)
+1, сколько сам писал, напишешь что-нить сложное, работает, надо поправить, проще с нуля написать, чем разобраться, что там было написано.
НЛО прилетело и опубликовало эту надпись здесь
попробовал придумать решение не требующее C++0x, получилось что-то типа этого:
только под msvc-8.0 и msvc-9.0 выдается результат 1010 (правильный), а под gcc 4.4.0 — 1000
#include <iostream>

typedef char Small;
class Big {char dummy[2]; };

template <size_t> struct ClassSelector {
    typedef Big type_;
};

template <> struct ClassSelector< sizeof(1)/sizeof(1) > {
    typedef Small type_;
};

#define DECLARE_IS_VALID_EXPRESSION( NAME, U_BASED_RUNTIME_EXPRESSION )\
template< class T > \
struct NAME\
{\
    template< typename U > static typename ClassSelector< sizeof( U_BASED_RUNTIME_EXPRESSION, 1 ) / sizeof( U_BASED_RUNTIME_EXPRESSION, 1 )>::type_ F( void * );\
    template< typename U > static typename ClassSelector<0>::type_ F( ... );\
    enum {  is_valid =  ( sizeof( F<T>( NULL ) ) != sizeof( ClassSelector<0>::type_ ) ) };\
};

struct Foo{ void f(); };
struct Bar{};

DECLARE_IS_VALID_EXPRESSION(HasF,  ( ( U * ) NULL )->f() );

DECLARE_IS_VALID_EXPRESSION(
    IsStreamSerializationSupported,
    ( (std::cout << *(U *)NULL), (std::cin >> *(U *)NULL) ) );

int main(int argc, char *argv[])
{
    std::cout  << HasF<Foo>::is_valid <<
            HasF<Bar>::is_valid <<
            IsStreamSerializationSupported<double>::is_valid <<
            IsStreamSerializationSupported<Bar>::is_valid ;
    return 0;
}
Не совсем понял как можно использовать этот шаблон для определения языковых конструкции, которые не должны компилироваться. Возможно ли это? В тестах такое бывает необходимо.
Дело в том, что в C++ есть 2 уровня проверки:

1. Минимальная проверка синтаксиса шаблона. Если шаблон ее проходит, значит есть ненулевая вероятность, что после инстанцирования его какими-либо типами/константами результат пройдет проверку №2.
2. Полная проверка выражений во время инстанцирования шаблона.

DECLARE_IS_VALID_EXPRESSION(...)
определяет шаблон, и к нему применяется только проверка №1.

BOOST_STATIC_ASSERT( HasF< A >::value )
инстанцирует шаблон HasF параметром A, применяется проверка №2.

Из этого следует, что если вы вставите на проверку код, где забыли закрыть скобку, использовали ключевое слово не так, как полагается и пр. шалости, код будет ill-formed. А код ( ( U * ) NULL )->f() вполне проходит проверку №1, потому что теоретически может существовать тип с методом f().
BOOST_STATIC_ASSERT( HasF< std::string >::value ) не проходит проверку №2, но по правилу SFINAE код компилируется.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации