在编译时检查字符的唯一性

MK.*_*MK. 6 c++ compile-time constexpr c++11

是否有可能在C++ 11(不是更晚)中编写一个函数来验证在编译时传递给它的字符的唯一性

verify('a');
verify('b');
verify('c');
verify('a');  //should cause compilation error
Run Code Online (Sandbox Code Playgroud)

[由MK编辑以回答一些问题]:

  • 呼叫始终在相同的范围内,如上所述一个接一个.
  • 宏观解决方案也是可以接受的
  • 非类型模板参数也是可接受的

Pat*_*ara 12

不完全是你要求的,但鉴于你的约束(相同的范围和宏解决方案是可以接受的)你可以尝试这样的事情:

#define verify(x) class _tmp_##x {};
Run Code Online (Sandbox Code Playgroud)

例:

int main()
{
    verify(a);
    verify(b);
    verify(a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

由于重新定义本地类而导致编译失败_tmp_a.


Yak*_*ont 8

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" )
Run Code Online (Sandbox Code Playgroud)

这应该在大小为2 ^ 100s的文件中工作,直到你的编译器内存不足,因为计数是对数深度递归.

该类型line_t启用延迟ADL查找,use_flag直到我们调用count_uses.我们对每个重载执行二叉树求和use_flag,每个字符在文件中每行一个.

实例.