4

Basicly I have volatile const char* and want to create a string. The volatile keyword here is in all likelyhood irrelevant(a misunderstanding from a previous dev), but cannot easily get rid of it (coming from other library).

cannot convert argument N from 'volatile const char *' to 'std::string

I could just use a const_cast to cast the volatile away (and making the compiler disregard volatile/const). Im interested in a solution not using const_cast.

Do other methods exist, eg. could using a stringstream perhaps be a solution ?

darune
  • 10,480
  • 2
  • 24
  • 62
  • 1
    @DanielsaysreinstateMonica I find that `const_cast` can make it hard to reason about code, and that raises more questions than it answers usually - it basicly just truncates the type. – darune Nov 11 '19 at 08:00
  • 2
    Then switch to a library that doesn't use `volatile` for no reason, that's the cleaner way. Second cleanest way is to just remove the `volatile`, for which `const_cast` is exactly the right tool. – Ulrich Eckhardt Nov 11 '19 at 08:02
  • 3
    Copy the characters to a non-volatile buffer? – Rlyeh Nov 11 '19 at 08:03
  • I just found out that this casting away `volatile` with `const_cast` [seemingly results in UB when accessing the data then](https://stackoverflow.com/a/24555400/580083). – Daniel Langr Nov 11 '19 at 08:08
  • The philosophical problem is that a `volatile` string (null-terminated array of `volatile char`) can change while you're reading it. Ans since you can't read it atomically, you can't rely on finding the null character when the string changes length externally. You need an out-of-band mechanism to safely determine the length of the string. – MSalters Nov 11 '19 at 13:27
  • @DanielsaysreinstateMonica Casting away a qualifier added by an implicit conversion is always well defined. We don't know how the data is defined and where the qualifier comes from. – curiousguy Nov 13 '19 at 03:41
  • @curiousguy: Say that the `\0` moves from position 20 to position 10, just when you're looking at position 15. After all, it can change outside the control of the running thread. – MSalters Nov 14 '19 at 08:04
  • @MSalters "_you can't rely on finding the null character when the string changes length externally._" I see what you mean. But then the protocol probably has a way to freeze the change of the string data until it is read, probably by setting another MMIO register to change where new data is written to, as otherwise the whole thing would be useless, as you would never know when you got a complete str. Conclusion: **We don't know enough about the com protocol here.** – curiousguy Nov 14 '19 at 16:13

2 Answers2

2

Just using a for loop, may be an option:

volatile const char* cstr = "hello world";
std::string str;
for (volatile const char* pC = *cstr ; *pC != 0; ++pC) {
    str.push_back(*pC);
}
darune
  • 10,480
  • 2
  • 24
  • 62
1

You can use the STL algorithm std::transform() to do an element-wise copy of your C string.

The transform function will effectively convert each volatile const char to a char -- a conversion that works without const_cast. Using std::back_inserter(), you can append the resulting characters to the end of your std::string.

#include <iostream>
#include <string>
#include <algorithm>

int main()
{
    volatile const char* cstr = "hello";
    std::size_t len = 6; // your string's length

    // this implicitly converts 'volatile const char' argument to 'char' parameter
    auto func = [] (char c) { return c; };
    std::string str;
    std::transform(cstr, cstr + len, std::back_inserter(str), func);

    std::cout << "string=" << str << ".\n"; // outputs:  string=hello.
}

Note that you cannot use std::strlen() for the same reason -- if you don't have the size, you need to write your own loop to calculate it.

TheOperator
  • 5,936
  • 29
  • 42
  • I do not have the length. It may be easier to just a for loop then. But i liked the idea of transform + back_inserter – darune Nov 11 '19 at 08:18
  • Yes, if you anyway need a loop, it may be easier to directly append to the string character by character. – TheOperator Nov 11 '19 at 08:50