2016-06-05 7 views
2

Я нашел этот код в сочетании с SFINAE:Странный SFINAE код

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

Как это работает? Он выглядит как безымянный массив параметров, но я не понимаю, как subscriptip помогает в разрешении перегрузки.

ответ

6

Границы массивов в C++ не могут быть равны нулю. Если выражение (например, I % 2 == 0) равно false, оно преобразуется в ноль, что приводит к недопустимому типу и, следовательно, к отказу замены.

По существу, это запутанная версия std::enable_if.

1

Помните, что это называется так: div<1234>() => Вызывается первая перегрузка.

Чтобы понять, вам нужно всего лишь взглянуть на аргумент:

char(*)[I % 2 == 0] = 0 Это означает, что указатель на массив символов. Этот массив имеет значение по умолчанию 0. Это означает, что вы также можете сделать char a[] = "hello world"; div<1234>(a);

I % 2 == 0 оценивается во время компиляции. Вы должны знать, что он делает. Даже целые числа делают это истинным, Нечетные целые значения делают это ложным. True оценивает значение 1, значение false равно 0. Однако нет такой вещи, как массив с нулевыми элементами. Это то, что вы называете ошибкой SFINAE. Это не значит, что это фундаментальная ошибка, просто что заготовки в шаблоне не могут быть заменены адекватно. Шаблон не подходит.

0

Как указано T.C. поскольку вы не можете иметь массивы из 0-элемента, когда условие является ложным, значение boolean false преобразуется в 0: тип становится char (*) [0] (указатель на массив символов размером 0), и это вызывает триггеры SFINAE.

Теперь, в более традиционных (и читаемым) способом, то, как правило, пусть std::enable_if сделать работу:

template <int I, std::enable_if_t<I%2>* = nullptr> 
div() { 
    std::cout << "I (" << I <<") am odd." << std::endl; 
} 

template <int I, std::enable_if_t<!(I%2)>* = nullptr> 
div() { 
    std::cout << "I (" << I <<") am even." << std::endl; 
} 

Как показано здесь на Coliru.

Смежные вопросы