Comments 14
UFO just landed and posted this here
Вот в такие моменты особенно D :)
Но красиво, да.
Но красиво, да.
0
UFO just landed and posted this here
Как я уже писал выше, has_xxx не позволяет проверять что угодно, конкретно boost::mpl умеет:
1. Проверять наличие типа с именем XXX внутри класса
2. Проверять наличие шаблонного типа template<… > class XXX внутри класса.
Оба примера, которые есть в посте (проверка наличия функции f()) и проверка, на возможность ввода/вывода через потоки не реализуемы на бусте.
1. Проверять наличие типа с именем XXX внутри класса
2. Проверять наличие шаблонного типа template<… > class XXX внутри класса.
Оба примера, которые есть в посте (проверка наличия функции f()) и проверка, на возможность ввода/вывода через потоки не реализуемы на бусте.
0
UFO just landed and posted this here
попробовал придумать решение не требующее C++0x, получилось что-то типа этого:
только под msvc-8.0 и msvc-9.0 выдается результат 1010 (правильный), а под gcc 4.4.0 — 1000
только под 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;
}
+2
Не совсем понял как можно использовать этот шаблон для определения языковых конструкции, которые не должны компилироваться. Возможно ли это? В тестах такое бывает необходимо.
0
Дело в том, что в C++ есть 2 уровня проверки:
1. Минимальная проверка синтаксиса шаблона. Если шаблон ее проходит, значит есть ненулевая вероятность, что после инстанцирования его какими-либо типами/константами результат пройдет проверку №2.
2. Полная проверка выражений во время инстанцирования шаблона.
Из этого следует, что если вы вставите на проверку код, где забыли закрыть скобку, использовали ключевое слово не так, как полагается и пр. шалости, код будет ill-formed. А код ( ( U * ) NULL )->f() вполне проходит проверку №1, потому что теоретически может существовать тип с методом f().
BOOST_STATIC_ASSERT( HasF< std::string >::value ) не проходит проверку №2, но по правилу SFINAE код компилируется.
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 код компилируется.
0
Only those users with full accounts are able to leave comments. Log in, please.
Шаблонная магия, метафункция IsValidExpression