Я думаю, что API is_rule
недостаточно.Например, unfortunate
- это правило, только если оно используется с итераторами типа const unsigned char*
.Если вы используете unfortunate
с const char*
, то это не сработает и, следовательно, не является правилом, верно?
Как говорится, если вы измените API на:
template <class R, class It> struct is_rule;
тогда я думаю, что это выполнимо в C ++ 11.Ниже приведен прототип:
#include <type_traits>
namespace axe
{
template <class It>
struct result
{
};
}
namespace detail
{
struct nat
{
nat() = delete;
nat(const nat&) = delete;
nat& operator=(const nat&) = delete;
~nat() = delete;
};
struct any
{
any(...);
nat operator()(any, any) const;
};
template <class T>
struct wrap
: public any,
public T
{
};
template <bool, class R, class It>
struct is_rule
{
typedef typename std::conditional<std::is_const<R>::value,
const wrap<R>,
wrap<R>>::type W;
typedef decltype(
std::declval<W>()(std::declval<It>(), std::declval<It>())
) type;
static const bool value = std::is_convertible<type, axe::result<It>>::value;
};
template <class R, class It>
struct is_rule<false, R, It>
{
static const bool value = false;
};
} // detail
template <class R, class It>
struct is_rule
: public std::integral_constant<bool,
detail::is_rule<std::is_class<R>::value, R, It>::value>
{
};
struct unfortunate
{
axe::result<const unsigned char*>
operator()(const unsigned char*, const unsigned char*);
};
#include <iostream>
int main()
{
std::cout << is_rule<unfortunate, const unsigned char*>::value << '\n';
std::cout << is_rule<unfortunate, const char*>::value << '\n';
}
Для меня это выводит на печать:
1
0
Я сделал правило немного более слабым, чем вы указали: тип возвращаемого значения должен быть только неявно конвертируемым вaxe::result<It>
.Если вы действительно хотите, чтобы он был точно axe::result<It>
, тогда просто подпишите в std::is_same
, где я использовал std::is_convertible
.
Я также сделал is_rule
производным от std::integral_constant
.Это может быть очень удобно для отправки тегов.Например:
template <class T>
void imp(T, std::false_type);
template <class T>
void imp(T, std::true_type);
template <class T>
void foo(T t) {imp(t, is_rule<T, const char*>());}