struct FOO{
int a;
int b;
int c;
};
volatile struct FOO foo;
int main(void)
{
foo.a = 10;
foo.b = 10;
foo.c = 10;
struct FOO test = foo
This is ill-formed because FOO
has an implicit copy constructor defined as:
FOO(FOO const&);
And you write FOO test = foo;
with foo
of type volatile FOO
, invoking:
FOO(volatile FOO const&);
But references-to-volatile to references-to-non-volatile implicit conversion is ill-formed.
From here, two solutions emerge:
const_cast
can remove the volatile qualifier, but this is undefined behavior to use that if your underlying object is effectively volatile.Could I possibly use memcopy() for that?
No you cannot, memcpy
is incompatible with volatile objects: thre is no overload of it which takes pointers-to-volatile, and there is nothing you can do without invoking undefined behavior.
So, as a conclusion, your best shot if you cannot add a constructor to FOO
is to define:
FOO FOO_copy(FOO volatile const& other)
{
FOO result;
result.a = other.a;
result.b = other.b;
result.c = other.c;
return result;
}
Or with C++11's std::tie:
FOO FOO_copy(FOO volatile const& other)
{
FOO result;
std::tie(result.a, result.b, result.c) = std::tie(other.a, other.b, other.c);
return result;
}
To give another approach to an answer, to address why this doesn't make sense, rather than just where the C++ standard says this is invalid:
The whole point of volatile
is that you have precise control over which variable gets accessed when. That means given volatile int i, j;
, i = 1; j = 2;
and j = 2; i = 1;
do not do the same thing. The compiler cannot freely transform one into the other. The same applies to reads: given volatile int i, j; int x, y;
, x = i; y = j;
and y = j; x = i;
do not do the same thing. The presence of volatile
means the accesses must happen in exactly the order you specified.
Now, in your example, what should struct FOO test = foo;
do? You've never specified whether you want to first read foo.a
, then foo.b
, finally foo.c
, or perhaps first read foo.c
, then foo.b
, finally foo.a
, or perhaps some other order.
You can, if you wish, do this:
struct FOO test;
test.a = foo.a;
test.b = foo.b;
test.c = foo.c;
Here, you explicitly specify the order of the accesses to foo
's fields, so you avoid the problem.
You haven't provided enough details about your problem to give a more precise assessment, but the solution to whatever problem you're trying to solve is almost certainly not to use volatile
. "Volatile" means that the value can change from under your feet: the two typical good use cases are variables changed from within UNIX signal handlers and memory-mapped registers. Volatile is not enough for variables shared among threads, notably.
The reason you are getting this error is that your compiler is trying to find a FOO(volatile FOO&)
copy constructor, which is never automatically generated.