C++ примеры SFINAE?

Наткнулся на эту тему, и это выглядело так весело, что я не смог устоять - вот еще одна версия JavaScript - она ​​не самая короткая, но мне нравится, как она использует рекурсию и замыкание внутри цикла.

(function(){
    var v = [
        {d:'first', p:'a partridge in a pear tree'},
        {d:'second', p:'two turtle doves, and '},
        {d:'third', p:'three french hens, '},
        {d:'fourth', p:'four calling birds, '},
        {d:'fifth', p:'five gold rings, '}, 
        {d:'sixth', p:'six geese a-laying, '}, 
        {d:'seventh', p:'seven swans a-swimming, '},
        {d:'eighth', p:'eight maids a-milking, '},
        {d:'ninth', p:'nine ladies dancing, '}, 
        {d:'tenth', p:'ten lords a-leaping, '},
        {d:'eleveth', p:'eleven pipers piping, '},
        {d:'twelth', p:'twelve drummers drumming, '}
    ];
    for (var i=0;i<12;i++)
    {
        document.write('On the '+v[i].d+' day of Christmas my true love gave to me ');
        (function(i){
            document.write(v[i].p);
            if (i>0)
            {
                arguments.callee(--i);
            }
        })(i);
        document.write('.<p>');
    }
})();
113
задан rlbond 11 June 2009 в 18:25
поделиться

3 ответа

Вот один пример ( отсюда ):

template<typename T>
class IsClassT {
  private:
    typedef char One;
    typedef struct { char a[2]; } Two;
    template<typename C> static One test(int C::*);
    // Will be chosen if T is anything except a class.
    template<typename C> static Two test(...);
  public:
    enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
    enum { No = !Yes };
};

Когда вычисляется IsClassT :: Yes , 0 не может быть преобразовано в int int :: * , потому что int не является классом, поэтому у него не может быть указателя на член. Если SFINAE не существует, вы получите ошибку компилятора, что-то вроде «0 не может быть преобразован в указатель на член для неклассового типа int». Вместо этого он просто использует ... form, которая возвращает Two и, таким образом, принимает значение false, int не является типом класса.

67
ответ дан 24 November 2019 в 02:43
поделиться

Мне нравится использовать SFINAE для проверки логических условий.

template<int I> void div(char(*)[I % 2 == 0] = 0) {
    /* this is taken when I is even */
}

template<int I> void div(char(*)[I % 2 == 1] = 0) {
    /* this is taken when I is odd */
}

Это может быть весьма полезно. Например, я использовал его, чтобы проверить, не превышает ли список инициализаторов, собранный с использованием операторной запятой, фиксированный размер

template<int N>
struct Vector {
    template<int M> 
    Vector(MyInitList<M> const& i, char(*)[M <= N] = 0) { /* ... */ }
}

. Список принимается только в том случае, если M меньше N, что означает, что список инициализаторов не содержит слишком много элементов.

Синтаксис char (*) [C] означает: Указатель на массив с типом элемента char и размером C . Если C ложно (здесь 0), то мы получаем недопустимый тип char (*) [0] , указатель на массив нулевого размера: SFINAE делает так, что шаблон будет игнорировать тогда.

Выражается с помощью boost :: enable_if , что выглядит так

template<int N>
struct Vector {
    template<int M> 
    Vector(MyInitList<M> const& i, 
           typename enable_if_c<(M <= N)>::type* = 0) { /* ... */ }
}

На практике я часто считаю способность проверять условия полезной способностью.

87
ответ дан 24 November 2019 в 02:43
поделиться

Библиотека Boost enable_if предлагает красивый чистый интерфейс для с помощью SFINAE. Один из моих любимых примеров использования - в библиотеке Boost.Iterator . SFINAE используется для преобразования типов итераторов.

9
ответ дан 24 November 2019 в 02:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: