Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
292 views
in Technique[技术] by (71.8m points)

c++ - Compile-time assert for string equality

Is this possible to do using templates?

There are two string constants. They come from defines in different modules. They must be equal, or I shall raise compile-time error if they are not equal. Can I do this using templates?

#define MY_STRING "foo"
CompileAssertIfStringsNotEqual(MY_STRING, HIS_STRING);

P.S. I was deluded by assuming that "abc"[0] is constant expression. It is not. Weird omission in the language. It would be possibe had "abc"[0] been constand expression.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is only possible with C++0x. No chance with C++03.

EDIT: Constexpr function for C++0x. The following works with GCC4.6, however the Standard is not explicit in allowing it, and a small wording tweak was and is being considered to make the spec allow it.

constexpr bool isequal(char const *one, char const *two) {
  *one == *two && (!*one || isEqual(one + 1, two + 1));
}

static_assert(isequal("foo", "foo"), "this should never fail");
static_assert(!isequal("foo", "bar"), "this should never fail");

The compiler is required to track the reference to characters of the string literals already, throughout all the recursions. Just the final read from characters isn't explicitly allowed (if you squint, you can read it as being allowed, IMO). If your compiler doesn't want to accept the above simple version, you can make your macro declare arrays and then compare those

#define CONCAT1(A, B) A ## B
#define CONCAT(A, B) CONCAT1(A, B)

#define CHECK_EQUAL(A, B) 
  constexpr char CONCAT(x1, __LINE__)[] = A, 
                 CONCAT(x2, __LINE__)[] = B; 
  static_assert(isequal(CONCAT(x1, __LINE__), CONCAT(x2, __LINE__)), 
     "'" A "' and '"  B "' are not equal!")

That's definitely fine.

CHECK_EQUAL("foo", "foo"); /* will pass */
CHECK_EQUAL("foo", "bar"); /* will fail */

Note that CHECK_EQUAL can be used inside of functions. The FCD did make a change to allow constexpr functions to read from automatic arrays in their invocation substitution. See DR1197.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...