3

This gives the error: cannot convert from 'const char *' to 'char *'.

class Mock
{
public:
    ...
    static void func(char **result)
    {
          *result = (resultsI++)->c_str();
    }
static std::vector<std::string> results;
static std::vector<std::string>::iterator resultsI;
};

std::vector<std::string> Mock::results;
std::vector<std::string>::iterator Mock::resultsI;

How can I validly get rid of this error without changing the interface to the function func? The implementer of this interface:

void (func*)(char **result) 

forgot to use const char** in the signature. I can't change it.

Remember this is a mock and I'm only used in my unit tests.

4
  • Guess you'll have to copy instead of using c_str(). Commented Nov 16, 2012 at 16:21
  • You could (but shouldn't) cast away the constness (const_cast<char*>((resultsI++)->c_str());) Commented Nov 16, 2012 at 16:24
  • Ryan Guthrie: Why shouldn't I do this? Commented Nov 16, 2012 at 16:24
  • const is there for your own protection. By casting it away, you lose that protection. Commented Nov 16, 2012 at 17:13

3 Answers 3

6

Try:

*result = &(*resultsI++)[0];

Although this isn't guaranteed to work prior to C++11 it is known to be OK on most or all current compilers.

The danger is that if the function tries to change the length of the string, you could get some nasty errors. Changing individual characters should be OK.

Sign up to request clarification or add additional context in comments.

5 Comments

So only C++11 has specified that std::string must have its memory contiguous?
@Kos: That's correct. Although most C++03 implementations I'm familiar with actually do use contiguous storage, this wasn't guaranteed in the C++03 Standard. When I need C++03 guaranteed contigious storage, I typically use vector<char> rather than string
@Kos, the guarantee was added to C++11 after a survey of all the committee members showed that their std::string implementations were already compliant.
@JohnDibling, I've used vector<char> too, it depends on the task. Sometimes it's great and sometimes not having the string methods makes it tedious.
The danger here is that any modification to the original string can cause it to move and their is no guarantee that it is '\0' terminated which may be a problem if you pass it to a C-String function. If I was doing something this dangerous I like to make it obvious that it is dangerous. By using a const_cast<char*>((resultsI++)->c_str()) you make it stick out because we know we should not be using const cast. That way you know your code is bad and it sticks out.
4

In test code, and if you are certain that the user of the interface isn't going to mutate the char*, maybe you could use a const_cast?

That assumes the caller doesn't take ownership of the char *; if that is the case, then you should make a copy.

Comments

4

If you're absolutely certain that the interface function will not modify the string, you can use

*result = const_cast<char *>((resultsI++)->c_str());

to remove constness.

Otherwise, another option is to switch from using std::vector<std::string> to std::vector<std::vector<char>> but then you'll have to make sure you properly null terminate the strings.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.