Проверка уникальности символов во время компиляции

Можно ли в C++11 (не позднее) написать функцию, которая проверяет уникальность символов, переданных ей во время компиляции

verify('a');
verify('b');
verify('c');
verify('a');  //should cause compilation error

[Редактировать М.К., чтобы ответить на несколько вопросов]:

  • Вызовы всегда находятся в одной и той же области, один за другим, как указано выше.
  • Макро-решение тоже будет приемлемым
  • Нетипичные параметры шаблона тоже приемлемы

2 ответа

Не совсем то, что вы просили, но с учетом ваших ограничений (те же рамки и макроподразделение приемлемо) вы можете попробовать что-то вроде этого:

#define verify(x) class _tmp_##x {};

Пример:

int main()
{
    verify(a);
    verify(b);
    verify(a);
    return 0;
}

Сбой компиляции из-за переопределения локального класса _tmp_a,

template<std::size_t X>
struct line_t { enum{value=X}; constexpr line_t(){} };

template<std::size_t line, char c>
constexpr std::integral_constant<bool, false> use_flag(
  std::integral_constant<char,c>, line_t<line>
) { return {}; }

#define FLAG_USE( C ) \
constexpr std::integral_constant<bool, true> use_flag( \
  std::integral_constant<char,C>, line_t<__LINE__> \
) { return {}; }

template<char c, std::size_t line>
constexpr std::size_t count_uses( line_t<line> from, line_t<1> length ){
  return use_flag( std::integral_constant<char, c>{}, from )();
}
template<char c, std::size_t line>
constexpr std::size_t count_uses( line_t<line> from, line_t<0> length ){
  return 0;
}

template<char c, std::size_t f, std::size_t l>
constexpr std::size_t count_uses(line_t<f> from, line_t<l> length ){
  return count_uses<c>( from, line_t< l/2 >{} )+ count_uses<c>( line_t< f+l/2>{}, line_t<(l+1)/2>{} );
}

#define UNIQUE(C) \
  FLAG_USE(C) \
  static_assert( count_uses<C>( line_t<0>{}, line_t<__LINE__+1>{} )==1, "too many" )

Это должно работать в файлах размером 2^100 с, пока ваш компилятор не исчерпает память, так как подсчет - это рекурсия по глубине журнала.

Тип line_t включает отложенный поиск ADL use_flag пока мы не призываем count_uses, Мы делаем двоичную сумму дерева по каждой перегрузке use_flagпо одному на строку на символ в файле.

Живой пример.

Другие вопросы по тегам