SFINAE + sizeof = определить, скомпилировано ли выражение - PullRequest
12 голосов
/ 24 января 2010

Я только что узнал, как проверить, предоставляется ли operator<< для типа.

template<class T> T& lvalue_of_type();
template<class T> T  rvalue_of_type();

template<class T>
struct is_printable
{
    template<class U> static char test(char(*)[sizeof(
        lvalue_of_type<std::ostream>() << rvalue_of_type<U>()
    )]);
    template<class U> static long test(...);

    enum { value = 1 == sizeof test<T>(0) };
    typedef boost::integral_constant<bool, value> type;
};

Этот трюк хорошо известен, или я только что выиграл Нобелевскую премию по метапрограммированию?;)

РЕДАКТИРОВАТЬ: я сделал код проще для понимания и легче адаптировать с помощью двух глобальных объявлений шаблонов функций lvalue_of_type и rvalue_of_type.

Ответы [ 2 ]

6 голосов
/ 24 января 2010

Боюсь, это хорошо известная техника: -)

Использование вызова функции в операторе sizeof инструктирует компилятор выполнять вывод аргументов и сопоставление функций, конечно же, во время компиляции. Кроме того, с помощью функции шаблона компилятор также создает конкретную функцию из шаблона. Однако это выражение не приводит к генерации вызова функции. Это хорошо описано в SFINAE Sono Buoni PDF.

Проверьте другие примеры C ++ SFINAE .

1 голос
/ 24 января 2010

Это просто комбинация двух известных трюков. SFINAE говорит, что «ошибка замещения не является ошибкой» - это именно то, что вы сделали. Использование sizeof, чтобы позволить компилятору подставлять аргументы шаблона в выражение, фактически не выполняя его, также распространено.

Извините: -)

...