0

I have some C++ code that looks like so:

std::string DataDirHelper(const std::string& file) {    
  #ifndef CRYPTOPP_DATA_DIR
    return file;
  #else
    std::string dataDir(CRYPTOPP_DATA_DIR);
    ...
  #endif
}

Is there a way to test that CRYPTOPP_DATA_DIR is a C-stirng (and not, say, an int)?

If so, how can I do it?

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
jww
  • 97,681
  • 90
  • 411
  • 885
  • Wouldn't you just get a compiler error if it's an int? – Oliver Charlesworth Apr 12 '15 at 21:46
  • This seems like a weird thing to test, like trying to assert within a for loop body that you didn't accidentally declare `i` as a string. Why do you need to do this? – user2357112 Apr 12 '15 at 21:54
  • @user2357112 - the problem is the user defines `CRYPTOPP_DATA_DIR`, and not the library. As soon as the user is allowed to make a choice, we have to plan for the unexpected things. Lord knows what they might come up with.... – jww Apr 12 '15 at 21:55
  • 2
    @jww: This may be helpful: http://stackoverflow.com/a/18565423/47453 – Bill Lynch Apr 12 '15 at 21:57
  • It would probably be more productive if you posted a question about the problem you're trying to solve, rather than the problem you ran into trying to make your solution work. –  Apr 12 '15 at 21:57
  • The user is in control of the code. Whatever is built belongs to her. Why complicate the matter? If it's rabbit Baby wants, [rabbit Baby gets](https://youtu.be/_VrRlMt8SF4)! – Dialecticus Apr 12 '15 at 22:03
  • @Hurkyl - I'm not sure what you mean. The problem I am trying to solve is: ensure `CRYPTOPP_DATA_DIR` is a C-string, and not something else dreamed up by a clever user in an effort to break the patch. The simplest way I can come up with is test that its what I expect. – jww Apr 12 '15 at 22:12
  • @jww: Why did you even come up with the idea of having a macro `CRYPTOPP_DATA_DIR` that needs to be a string literal or undefined? The answer to that question is what I mean by "the problem you're trying to solve", and there may very well be better approaches to solving that problem than what you're trying to do with `CRYPTOPP_DATA_DIR`. (although sometimes this line of inquiry needs to be iterated a few times, because the kink in the design is at a much higher level) –  Apr 12 '15 at 22:52
  • @Hurkyl - what you seem to be missing is this is a third party patch to the library. It may (or may not) be used, and it may (or may not) be used the way that's intended. Because its a patch, it needs to make a minimal number of changes. And it needs to be easy to use and integrate with the current build system. Its as much a political problem as it is a robustness problem. If it was just a technical problem, then the solution would be easier. – jww Apr 12 '15 at 23:18
  • @jww: I already see one small tweak that seems to solve the problem you're trying to solve, but without the problem you're facing (although it may introduce new problems?): rather than require the user to put the double quotes into the macro, simply make the macro the text and use the preprocessor to stringize it. –  Apr 12 '15 at 23:34
  • Thanks @Hurkyl. I've already told you the problem I am trying to solve. I'm not really interested in an endless debate with you. Thanks for the attempt to help, though. – jww Apr 12 '15 at 23:57

1 Answers1

3

The simplest solution is:

std::string DataDirHelper(const std::string& file) {    
  #ifndef CRYPTOPP_DATA_DIR
    return file;
  #else
    std::string dataDir("" CRYPTOPP_DATA_DIR);
    ...
  #endif
}

When CRYPTOPP_DATA_DIR is a string literal, the compiler will merge it with the adjacent empty string. When it is not a string literal, it may still compile if the macro is sufficiently awful (with some leading commas and what not).

Alternatively, we could use the requirement that static_assert requires a string literal as an argument. Thus, we could write this code:

std::string DataDirHelper(const std::string& file) {    
    static_assert(true, CRYPTOPP_DATA_DIR);
    std::string dataDir("" CRYPTOPP_DATA_DIR);
    ...
}

If CRYPTOPP_DATA_DIR was not a string literal, you would see an error message like this:

foo.cc:12:9: error: expected string literal
static_assert(true, CRYPTOPP_DATA_DIR);
                    ^~~~~~~~~~~~~~~~~
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • @jww: I've added some actual text to the answer. – Bill Lynch Apr 12 '15 at 22:01
  • Thanks @Bill. Should this be closed as a duplicate based on the other question you cited? If so, I'll cast the first close (I can't tell how similar they are). – jww Apr 12 '15 at 22:04
  • @jww: They're fairly similar. I've closed it as a duplicate since you're not too worried. – Bill Lynch Apr 12 '15 at 22:05
  • Thanks Bill. Sorry about the extra noise. – jww Apr 12 '15 at 22:09
  • @gomons: This code will compile, which I'd like my answer to reject: http://ideone.com/lyTSnF – Bill Lynch Apr 12 '15 at 23:10
  • I avoided the `static_assert` because its not available in older versions of C++, like 03. But I used the concatenation trick. See [Crypto++ DataDir Patch](http://www.cryptopp.com/wiki/DataDir#Patch). Thanks for the help. – jww Apr 12 '15 at 23:23