1
votes

I do have a program which makes use of volatile-qualified std::chrono::duration objects. Apparently, such objects become very hard to use. For example, following simple program produces compilation error (on gcc and clang):

#include <chrono>

volatile std::chrono::nanoseconds s;

void foo(std::chrono::nanoseconds k) {
    s = k;
}

error: passing 'volatile nanoseconds' {aka 'volatile std::chrono::duration >'} as 'this' argument discards qualifiers [-fpermissive]

It is obvious why I have this error given the interface of the class, and I also know how to hakishly make it "work" (undefined-behavior wise) with const_cast.

Having said that, can absence of volatile-qualified members of std::chrono::duration considered to be a defect? After all, volatile is a perfectly legal C++ construct, and although rare in use, has it's applications.

P.S. I would like to leave the wisdom of volatile-qualification outside of this question, but my crystal ball tells me it is not to be, so to preempt all 'you do not need volatile because it is not thread-safe' mantra, let's consider the case of a signal handler.

1
I'm not sure I would say this is a defect. AFAIK, pretty much everything in the standard library is not overloaded to deal with volatile. I think this was a design decision, although I'm not sure what the reason would be.NathanOliver
FWIW, volatile is not required to work properly with a signal handler. Prior to 2011 the only acceptable type was sig_atomic_t. In C++ 11 you can also use various atomic types.Pete Becker

1 Answers

5
votes

Except for very low level facilities, the std::lib doesn't really deal with volatile at all. One could argue that chrono is so low-level that it should handle volatile qualifications. I don't know if the committee would buy that argument or not.

One can work around such restrictions. You mentioned const_cast. I'd actually recommend casting back and forth from the underlying integral type. It is one of the very few circumstances where I recommend doing so. And it could be encapsulated in a little function:

#include <chrono>

volatile std::chrono::nanoseconds::rep s;

void
set_s(std::chrono::nanoseconds k)
{
    s = k.count();
}

std::chrono::nanoseconds
get_s()
{
    return std::chrono::nanoseconds{s};
}

void foo(std::chrono::nanoseconds k) {
    set_s(k);
}