Proper way to call a c-function taking non-const pointer arguments, const_cast, reinterpret_cast, launder












1














What is proper way to call a c-function taking non-const custom pointer arguments from c++?



Take, as a very common example, the function fftw_plan_dft_1d from FFTW3. http://fftw.org/fftw3_doc/Complex-DFTs.html#Complex-DFTs



fftw_plan fftw_plan_dft_1d(int n0,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags);


(fftw_complex is a typedef for double[2]).



Suppose I want apply this function to a couple of const-correct c++ containers.



std::vector<std::complex<double>> const In = {...};
std::vector<std::complex<double>> Out(In.size());


How should I do that?



_ First iteration, I have to extract the data pointer from the container,



assert(In.size() == Out.size());
fftw_plan fftw_plan_dft_1d(In.size(),
In.data(), Out.data(), // error const
FFTW_FORWARD, FFTW_ESTIMATE);


_ Second iteration



but since it is const I have to constcast.
I assume that this is the only possible solution assuming that the reason for the C-interfact is that C doesn't have const arguments.



fftw_plan p = fftw_plan_dft_1d(In.size(),
const_cast<std::complex<double>*>(In.data()), // error std::complex is not convertible to fftw_complex
Out.data(),
FFTW_FORWARD, FFTW_ESTIMATE);


_ Third iteration



Now, I have to convert std::complex<double> to fftw_complex (double[2]). Fortunately std::complex<double> is required to have the same layout as double[2].



fftw_plan p = fftw_plan_dft_1d(In.size(),
reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(In.data())), // is this UB?
reinterpret_cast<fftw_complex*>(Out.data()),
FFTW_FORWARD, FFTW_ESTIMATE);


and now I am paranoid, apparently reinterpret_cast is always UB.
I don't know how to use std::launder but I know that it can save reinterpret_cast UB in certain situations.



fftw_plan p = fftw_plan_dft_1d(In.size(),
std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(In.data()))), // needs c++17
std::launder(reinterpret_cast<fftw_complex*>(Out.data())),
FFTW_FORWARD, FFTW_ESTIMATE);


At the end of the day, is this a reasonable way to call a C-function that involves const and reinterpretation of types?



Am I too paranoid? or is it just that calling C from C++ is always formally UB in cases like these and I can't do anything about it?










share|improve this question




















  • 2




    C does have const (since C89/C90) but some poorly written libraries do not use it in their function prototypes.
    – TypeIA
    Nov 13 '18 at 0:07










  • @TypeIA, I noticed that, what should one do in those cases? break const correctness from the beginning or use const_cast. To be clear in this case, the only reason I know that I can pass a const pointer to this library is because of the last parameter FFTW_ESTIMATE which promises not overwrite the data of first pointer.
    – alfC
    Nov 13 '18 at 0:11
















1














What is proper way to call a c-function taking non-const custom pointer arguments from c++?



Take, as a very common example, the function fftw_plan_dft_1d from FFTW3. http://fftw.org/fftw3_doc/Complex-DFTs.html#Complex-DFTs



fftw_plan fftw_plan_dft_1d(int n0,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags);


(fftw_complex is a typedef for double[2]).



Suppose I want apply this function to a couple of const-correct c++ containers.



std::vector<std::complex<double>> const In = {...};
std::vector<std::complex<double>> Out(In.size());


How should I do that?



_ First iteration, I have to extract the data pointer from the container,



assert(In.size() == Out.size());
fftw_plan fftw_plan_dft_1d(In.size(),
In.data(), Out.data(), // error const
FFTW_FORWARD, FFTW_ESTIMATE);


_ Second iteration



but since it is const I have to constcast.
I assume that this is the only possible solution assuming that the reason for the C-interfact is that C doesn't have const arguments.



fftw_plan p = fftw_plan_dft_1d(In.size(),
const_cast<std::complex<double>*>(In.data()), // error std::complex is not convertible to fftw_complex
Out.data(),
FFTW_FORWARD, FFTW_ESTIMATE);


_ Third iteration



Now, I have to convert std::complex<double> to fftw_complex (double[2]). Fortunately std::complex<double> is required to have the same layout as double[2].



fftw_plan p = fftw_plan_dft_1d(In.size(),
reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(In.data())), // is this UB?
reinterpret_cast<fftw_complex*>(Out.data()),
FFTW_FORWARD, FFTW_ESTIMATE);


and now I am paranoid, apparently reinterpret_cast is always UB.
I don't know how to use std::launder but I know that it can save reinterpret_cast UB in certain situations.



fftw_plan p = fftw_plan_dft_1d(In.size(),
std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(In.data()))), // needs c++17
std::launder(reinterpret_cast<fftw_complex*>(Out.data())),
FFTW_FORWARD, FFTW_ESTIMATE);


At the end of the day, is this a reasonable way to call a C-function that involves const and reinterpretation of types?



Am I too paranoid? or is it just that calling C from C++ is always formally UB in cases like these and I can't do anything about it?










share|improve this question




















  • 2




    C does have const (since C89/C90) but some poorly written libraries do not use it in their function prototypes.
    – TypeIA
    Nov 13 '18 at 0:07










  • @TypeIA, I noticed that, what should one do in those cases? break const correctness from the beginning or use const_cast. To be clear in this case, the only reason I know that I can pass a const pointer to this library is because of the last parameter FFTW_ESTIMATE which promises not overwrite the data of first pointer.
    – alfC
    Nov 13 '18 at 0:11














1












1








1







What is proper way to call a c-function taking non-const custom pointer arguments from c++?



Take, as a very common example, the function fftw_plan_dft_1d from FFTW3. http://fftw.org/fftw3_doc/Complex-DFTs.html#Complex-DFTs



fftw_plan fftw_plan_dft_1d(int n0,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags);


(fftw_complex is a typedef for double[2]).



Suppose I want apply this function to a couple of const-correct c++ containers.



std::vector<std::complex<double>> const In = {...};
std::vector<std::complex<double>> Out(In.size());


How should I do that?



_ First iteration, I have to extract the data pointer from the container,



assert(In.size() == Out.size());
fftw_plan fftw_plan_dft_1d(In.size(),
In.data(), Out.data(), // error const
FFTW_FORWARD, FFTW_ESTIMATE);


_ Second iteration



but since it is const I have to constcast.
I assume that this is the only possible solution assuming that the reason for the C-interfact is that C doesn't have const arguments.



fftw_plan p = fftw_plan_dft_1d(In.size(),
const_cast<std::complex<double>*>(In.data()), // error std::complex is not convertible to fftw_complex
Out.data(),
FFTW_FORWARD, FFTW_ESTIMATE);


_ Third iteration



Now, I have to convert std::complex<double> to fftw_complex (double[2]). Fortunately std::complex<double> is required to have the same layout as double[2].



fftw_plan p = fftw_plan_dft_1d(In.size(),
reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(In.data())), // is this UB?
reinterpret_cast<fftw_complex*>(Out.data()),
FFTW_FORWARD, FFTW_ESTIMATE);


and now I am paranoid, apparently reinterpret_cast is always UB.
I don't know how to use std::launder but I know that it can save reinterpret_cast UB in certain situations.



fftw_plan p = fftw_plan_dft_1d(In.size(),
std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(In.data()))), // needs c++17
std::launder(reinterpret_cast<fftw_complex*>(Out.data())),
FFTW_FORWARD, FFTW_ESTIMATE);


At the end of the day, is this a reasonable way to call a C-function that involves const and reinterpretation of types?



Am I too paranoid? or is it just that calling C from C++ is always formally UB in cases like these and I can't do anything about it?










share|improve this question















What is proper way to call a c-function taking non-const custom pointer arguments from c++?



Take, as a very common example, the function fftw_plan_dft_1d from FFTW3. http://fftw.org/fftw3_doc/Complex-DFTs.html#Complex-DFTs



fftw_plan fftw_plan_dft_1d(int n0,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags);


(fftw_complex is a typedef for double[2]).



Suppose I want apply this function to a couple of const-correct c++ containers.



std::vector<std::complex<double>> const In = {...};
std::vector<std::complex<double>> Out(In.size());


How should I do that?



_ First iteration, I have to extract the data pointer from the container,



assert(In.size() == Out.size());
fftw_plan fftw_plan_dft_1d(In.size(),
In.data(), Out.data(), // error const
FFTW_FORWARD, FFTW_ESTIMATE);


_ Second iteration



but since it is const I have to constcast.
I assume that this is the only possible solution assuming that the reason for the C-interfact is that C doesn't have const arguments.



fftw_plan p = fftw_plan_dft_1d(In.size(),
const_cast<std::complex<double>*>(In.data()), // error std::complex is not convertible to fftw_complex
Out.data(),
FFTW_FORWARD, FFTW_ESTIMATE);


_ Third iteration



Now, I have to convert std::complex<double> to fftw_complex (double[2]). Fortunately std::complex<double> is required to have the same layout as double[2].



fftw_plan p = fftw_plan_dft_1d(In.size(),
reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(In.data())), // is this UB?
reinterpret_cast<fftw_complex*>(Out.data()),
FFTW_FORWARD, FFTW_ESTIMATE);


and now I am paranoid, apparently reinterpret_cast is always UB.
I don't know how to use std::launder but I know that it can save reinterpret_cast UB in certain situations.



fftw_plan p = fftw_plan_dft_1d(In.size(),
std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(In.data()))), // needs c++17
std::launder(reinterpret_cast<fftw_complex*>(Out.data())),
FFTW_FORWARD, FFTW_ESTIMATE);


At the end of the day, is this a reasonable way to call a C-function that involves const and reinterpretation of types?



Am I too paranoid? or is it just that calling C from C++ is always formally UB in cases like these and I can't do anything about it?







c c++17 reinterpret-cast const-cast






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 0:12

























asked Nov 13 '18 at 0:05









alfC

4,94722858




4,94722858








  • 2




    C does have const (since C89/C90) but some poorly written libraries do not use it in their function prototypes.
    – TypeIA
    Nov 13 '18 at 0:07










  • @TypeIA, I noticed that, what should one do in those cases? break const correctness from the beginning or use const_cast. To be clear in this case, the only reason I know that I can pass a const pointer to this library is because of the last parameter FFTW_ESTIMATE which promises not overwrite the data of first pointer.
    – alfC
    Nov 13 '18 at 0:11














  • 2




    C does have const (since C89/C90) but some poorly written libraries do not use it in their function prototypes.
    – TypeIA
    Nov 13 '18 at 0:07










  • @TypeIA, I noticed that, what should one do in those cases? break const correctness from the beginning or use const_cast. To be clear in this case, the only reason I know that I can pass a const pointer to this library is because of the last parameter FFTW_ESTIMATE which promises not overwrite the data of first pointer.
    – alfC
    Nov 13 '18 at 0:11








2




2




C does have const (since C89/C90) but some poorly written libraries do not use it in their function prototypes.
– TypeIA
Nov 13 '18 at 0:07




C does have const (since C89/C90) but some poorly written libraries do not use it in their function prototypes.
– TypeIA
Nov 13 '18 at 0:07












@TypeIA, I noticed that, what should one do in those cases? break const correctness from the beginning or use const_cast. To be clear in this case, the only reason I know that I can pass a const pointer to this library is because of the last parameter FFTW_ESTIMATE which promises not overwrite the data of first pointer.
– alfC
Nov 13 '18 at 0:11




@TypeIA, I noticed that, what should one do in those cases? break const correctness from the beginning or use const_cast. To be clear in this case, the only reason I know that I can pass a const pointer to this library is because of the last parameter FFTW_ESTIMATE which promises not overwrite the data of first pointer.
– alfC
Nov 13 '18 at 0:11












1 Answer
1






active

oldest

votes


















3














I think you're indeed being quite paranoid, and I also think that's a good thing. Keep it up. A little paranoia will greatly reduce the number of times you shoot yourself in the foot!



You correctly identified the need to cast away the const qualifier because the library doesn't use const in its function signature. And you correctly identified the solution using const_cast<>.



You also correctly identified that reinterpret_cast<> is technically UB in this situation if you don't assume that fftw_complex is typedefed as double[2]. (I'm not familiar with FFTW3, so I don't know if that is even true or not, but you probably do.) If you know it's a typedef, it is not UB because the types are the same, just aliased under different names. If you don't know, it's "probably" still safe, but yes, I think that might be a case where you have to make a little leap of faith, knowing that any sane, real world compiler should do the right thing. There's a note to this effect in the FFTW3 documentation.




C++ has its own complex template class, defined in the standard header file. Reportedly, the C++ standards committee has recently agreed to mandate that the storage format used for this type be binary-compatible with the C99 type, i.e. an array T[2] with consecutive real [0] and imaginary [1] parts. (See report http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2002/n1388.pdf WG21/N1388.) Although not part of the official standard as of this writing, the proposal stated that: “This solution has been tested with all current major implementations of the standard library and shown to be working.” To the extent that this is true, if you have a variable complex *x, you can pass it directly to FFTW via reinterpret_cast(x).




(Of course this layout guarantee is now part of the standard as of C++11.)



Finally, a note about C++ style casts. Everyone says you should use them instead of C casts, and this is true in most situations, but C-style casts are well-defined and the program isn't going to blow up if you use them. The tradeoff is one of conciseness and readable code (C-style) against explicit declaration of intent (C++-style). The exact rules for what the C++ compiler does with C-style casts are defined here. In my personal opinion, since you're already dealing with a C library with less-than-perfect function signatures, it is not the end of the world to simply C-style cast to a (double *) and call it a day.






share|improve this answer























  • fftw_complex is a typedef of double[2] the problem is that I am reinterpreting from std::complex<double>& to double[2]&. std::complex is indeed now mandated to have double[2] layout, what I don't know if that saves reinterpret_cast from being UB, cppreference seems to say that reinterpret is ok here (at least for refences, doesn't say anything about pointers) en.cppreference.com/w/cpp/numeric/complex.
    – alfC
    Nov 13 '18 at 1:25










  • I am tempted from you answer to say that all the paranoia of std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(in))) can be simply replaced by (fftw_complex*)in, because I am using C-library anyway. Good. (BTW there is no cast to (double*) involved I think.)
    – alfC
    Nov 13 '18 at 1:29












  • It means reinterpret_cast isn't needed at all, because given p = &c[0], p and p + 1 are guaranteed to be addresses of valid doubles and that's all you need (minus casting away the const). I agree that std::launder() seems like overkill and personally I would probably write const_cast<double *>(&c[0][0]) but I see nothing wrong with the C-style cast version.
    – TypeIA
    Nov 13 '18 at 1:43










  • Also maybe worth observing that the layout guarantees of std::vector come into play here too, such that given std::vector<std::complex> v, you can safely assume that the double components of each complex value are all packed at consecutive memory addresses.
    – TypeIA
    Nov 13 '18 at 1:44










  • Thanks, you say that reinterpret_cast is not needed at all, but how would you call fftw_plan_dft_1d on std::vector<std::complex<double>> without using reinterpret_cast or c-style cast? I don't see how.
    – alfC
    Nov 13 '18 at 3:41











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53271883%2fproper-way-to-call-a-c-function-taking-non-const-pointer-arguments-const-cast%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














I think you're indeed being quite paranoid, and I also think that's a good thing. Keep it up. A little paranoia will greatly reduce the number of times you shoot yourself in the foot!



You correctly identified the need to cast away the const qualifier because the library doesn't use const in its function signature. And you correctly identified the solution using const_cast<>.



You also correctly identified that reinterpret_cast<> is technically UB in this situation if you don't assume that fftw_complex is typedefed as double[2]. (I'm not familiar with FFTW3, so I don't know if that is even true or not, but you probably do.) If you know it's a typedef, it is not UB because the types are the same, just aliased under different names. If you don't know, it's "probably" still safe, but yes, I think that might be a case where you have to make a little leap of faith, knowing that any sane, real world compiler should do the right thing. There's a note to this effect in the FFTW3 documentation.




C++ has its own complex template class, defined in the standard header file. Reportedly, the C++ standards committee has recently agreed to mandate that the storage format used for this type be binary-compatible with the C99 type, i.e. an array T[2] with consecutive real [0] and imaginary [1] parts. (See report http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2002/n1388.pdf WG21/N1388.) Although not part of the official standard as of this writing, the proposal stated that: “This solution has been tested with all current major implementations of the standard library and shown to be working.” To the extent that this is true, if you have a variable complex *x, you can pass it directly to FFTW via reinterpret_cast(x).




(Of course this layout guarantee is now part of the standard as of C++11.)



Finally, a note about C++ style casts. Everyone says you should use them instead of C casts, and this is true in most situations, but C-style casts are well-defined and the program isn't going to blow up if you use them. The tradeoff is one of conciseness and readable code (C-style) against explicit declaration of intent (C++-style). The exact rules for what the C++ compiler does with C-style casts are defined here. In my personal opinion, since you're already dealing with a C library with less-than-perfect function signatures, it is not the end of the world to simply C-style cast to a (double *) and call it a day.






share|improve this answer























  • fftw_complex is a typedef of double[2] the problem is that I am reinterpreting from std::complex<double>& to double[2]&. std::complex is indeed now mandated to have double[2] layout, what I don't know if that saves reinterpret_cast from being UB, cppreference seems to say that reinterpret is ok here (at least for refences, doesn't say anything about pointers) en.cppreference.com/w/cpp/numeric/complex.
    – alfC
    Nov 13 '18 at 1:25










  • I am tempted from you answer to say that all the paranoia of std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(in))) can be simply replaced by (fftw_complex*)in, because I am using C-library anyway. Good. (BTW there is no cast to (double*) involved I think.)
    – alfC
    Nov 13 '18 at 1:29












  • It means reinterpret_cast isn't needed at all, because given p = &c[0], p and p + 1 are guaranteed to be addresses of valid doubles and that's all you need (minus casting away the const). I agree that std::launder() seems like overkill and personally I would probably write const_cast<double *>(&c[0][0]) but I see nothing wrong with the C-style cast version.
    – TypeIA
    Nov 13 '18 at 1:43










  • Also maybe worth observing that the layout guarantees of std::vector come into play here too, such that given std::vector<std::complex> v, you can safely assume that the double components of each complex value are all packed at consecutive memory addresses.
    – TypeIA
    Nov 13 '18 at 1:44










  • Thanks, you say that reinterpret_cast is not needed at all, but how would you call fftw_plan_dft_1d on std::vector<std::complex<double>> without using reinterpret_cast or c-style cast? I don't see how.
    – alfC
    Nov 13 '18 at 3:41
















3














I think you're indeed being quite paranoid, and I also think that's a good thing. Keep it up. A little paranoia will greatly reduce the number of times you shoot yourself in the foot!



You correctly identified the need to cast away the const qualifier because the library doesn't use const in its function signature. And you correctly identified the solution using const_cast<>.



You also correctly identified that reinterpret_cast<> is technically UB in this situation if you don't assume that fftw_complex is typedefed as double[2]. (I'm not familiar with FFTW3, so I don't know if that is even true or not, but you probably do.) If you know it's a typedef, it is not UB because the types are the same, just aliased under different names. If you don't know, it's "probably" still safe, but yes, I think that might be a case where you have to make a little leap of faith, knowing that any sane, real world compiler should do the right thing. There's a note to this effect in the FFTW3 documentation.




C++ has its own complex template class, defined in the standard header file. Reportedly, the C++ standards committee has recently agreed to mandate that the storage format used for this type be binary-compatible with the C99 type, i.e. an array T[2] with consecutive real [0] and imaginary [1] parts. (See report http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2002/n1388.pdf WG21/N1388.) Although not part of the official standard as of this writing, the proposal stated that: “This solution has been tested with all current major implementations of the standard library and shown to be working.” To the extent that this is true, if you have a variable complex *x, you can pass it directly to FFTW via reinterpret_cast(x).




(Of course this layout guarantee is now part of the standard as of C++11.)



Finally, a note about C++ style casts. Everyone says you should use them instead of C casts, and this is true in most situations, but C-style casts are well-defined and the program isn't going to blow up if you use them. The tradeoff is one of conciseness and readable code (C-style) against explicit declaration of intent (C++-style). The exact rules for what the C++ compiler does with C-style casts are defined here. In my personal opinion, since you're already dealing with a C library with less-than-perfect function signatures, it is not the end of the world to simply C-style cast to a (double *) and call it a day.






share|improve this answer























  • fftw_complex is a typedef of double[2] the problem is that I am reinterpreting from std::complex<double>& to double[2]&. std::complex is indeed now mandated to have double[2] layout, what I don't know if that saves reinterpret_cast from being UB, cppreference seems to say that reinterpret is ok here (at least for refences, doesn't say anything about pointers) en.cppreference.com/w/cpp/numeric/complex.
    – alfC
    Nov 13 '18 at 1:25










  • I am tempted from you answer to say that all the paranoia of std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(in))) can be simply replaced by (fftw_complex*)in, because I am using C-library anyway. Good. (BTW there is no cast to (double*) involved I think.)
    – alfC
    Nov 13 '18 at 1:29












  • It means reinterpret_cast isn't needed at all, because given p = &c[0], p and p + 1 are guaranteed to be addresses of valid doubles and that's all you need (minus casting away the const). I agree that std::launder() seems like overkill and personally I would probably write const_cast<double *>(&c[0][0]) but I see nothing wrong with the C-style cast version.
    – TypeIA
    Nov 13 '18 at 1:43










  • Also maybe worth observing that the layout guarantees of std::vector come into play here too, such that given std::vector<std::complex> v, you can safely assume that the double components of each complex value are all packed at consecutive memory addresses.
    – TypeIA
    Nov 13 '18 at 1:44










  • Thanks, you say that reinterpret_cast is not needed at all, but how would you call fftw_plan_dft_1d on std::vector<std::complex<double>> without using reinterpret_cast or c-style cast? I don't see how.
    – alfC
    Nov 13 '18 at 3:41














3












3








3






I think you're indeed being quite paranoid, and I also think that's a good thing. Keep it up. A little paranoia will greatly reduce the number of times you shoot yourself in the foot!



You correctly identified the need to cast away the const qualifier because the library doesn't use const in its function signature. And you correctly identified the solution using const_cast<>.



You also correctly identified that reinterpret_cast<> is technically UB in this situation if you don't assume that fftw_complex is typedefed as double[2]. (I'm not familiar with FFTW3, so I don't know if that is even true or not, but you probably do.) If you know it's a typedef, it is not UB because the types are the same, just aliased under different names. If you don't know, it's "probably" still safe, but yes, I think that might be a case where you have to make a little leap of faith, knowing that any sane, real world compiler should do the right thing. There's a note to this effect in the FFTW3 documentation.




C++ has its own complex template class, defined in the standard header file. Reportedly, the C++ standards committee has recently agreed to mandate that the storage format used for this type be binary-compatible with the C99 type, i.e. an array T[2] with consecutive real [0] and imaginary [1] parts. (See report http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2002/n1388.pdf WG21/N1388.) Although not part of the official standard as of this writing, the proposal stated that: “This solution has been tested with all current major implementations of the standard library and shown to be working.” To the extent that this is true, if you have a variable complex *x, you can pass it directly to FFTW via reinterpret_cast(x).




(Of course this layout guarantee is now part of the standard as of C++11.)



Finally, a note about C++ style casts. Everyone says you should use them instead of C casts, and this is true in most situations, but C-style casts are well-defined and the program isn't going to blow up if you use them. The tradeoff is one of conciseness and readable code (C-style) against explicit declaration of intent (C++-style). The exact rules for what the C++ compiler does with C-style casts are defined here. In my personal opinion, since you're already dealing with a C library with less-than-perfect function signatures, it is not the end of the world to simply C-style cast to a (double *) and call it a day.






share|improve this answer














I think you're indeed being quite paranoid, and I also think that's a good thing. Keep it up. A little paranoia will greatly reduce the number of times you shoot yourself in the foot!



You correctly identified the need to cast away the const qualifier because the library doesn't use const in its function signature. And you correctly identified the solution using const_cast<>.



You also correctly identified that reinterpret_cast<> is technically UB in this situation if you don't assume that fftw_complex is typedefed as double[2]. (I'm not familiar with FFTW3, so I don't know if that is even true or not, but you probably do.) If you know it's a typedef, it is not UB because the types are the same, just aliased under different names. If you don't know, it's "probably" still safe, but yes, I think that might be a case where you have to make a little leap of faith, knowing that any sane, real world compiler should do the right thing. There's a note to this effect in the FFTW3 documentation.




C++ has its own complex template class, defined in the standard header file. Reportedly, the C++ standards committee has recently agreed to mandate that the storage format used for this type be binary-compatible with the C99 type, i.e. an array T[2] with consecutive real [0] and imaginary [1] parts. (See report http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2002/n1388.pdf WG21/N1388.) Although not part of the official standard as of this writing, the proposal stated that: “This solution has been tested with all current major implementations of the standard library and shown to be working.” To the extent that this is true, if you have a variable complex *x, you can pass it directly to FFTW via reinterpret_cast(x).




(Of course this layout guarantee is now part of the standard as of C++11.)



Finally, a note about C++ style casts. Everyone says you should use them instead of C casts, and this is true in most situations, but C-style casts are well-defined and the program isn't going to blow up if you use them. The tradeoff is one of conciseness and readable code (C-style) against explicit declaration of intent (C++-style). The exact rules for what the C++ compiler does with C-style casts are defined here. In my personal opinion, since you're already dealing with a C library with less-than-perfect function signatures, it is not the end of the world to simply C-style cast to a (double *) and call it a day.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 13 '18 at 1:47

























answered Nov 13 '18 at 0:25









TypeIA

13.7k2241




13.7k2241












  • fftw_complex is a typedef of double[2] the problem is that I am reinterpreting from std::complex<double>& to double[2]&. std::complex is indeed now mandated to have double[2] layout, what I don't know if that saves reinterpret_cast from being UB, cppreference seems to say that reinterpret is ok here (at least for refences, doesn't say anything about pointers) en.cppreference.com/w/cpp/numeric/complex.
    – alfC
    Nov 13 '18 at 1:25










  • I am tempted from you answer to say that all the paranoia of std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(in))) can be simply replaced by (fftw_complex*)in, because I am using C-library anyway. Good. (BTW there is no cast to (double*) involved I think.)
    – alfC
    Nov 13 '18 at 1:29












  • It means reinterpret_cast isn't needed at all, because given p = &c[0], p and p + 1 are guaranteed to be addresses of valid doubles and that's all you need (minus casting away the const). I agree that std::launder() seems like overkill and personally I would probably write const_cast<double *>(&c[0][0]) but I see nothing wrong with the C-style cast version.
    – TypeIA
    Nov 13 '18 at 1:43










  • Also maybe worth observing that the layout guarantees of std::vector come into play here too, such that given std::vector<std::complex> v, you can safely assume that the double components of each complex value are all packed at consecutive memory addresses.
    – TypeIA
    Nov 13 '18 at 1:44










  • Thanks, you say that reinterpret_cast is not needed at all, but how would you call fftw_plan_dft_1d on std::vector<std::complex<double>> without using reinterpret_cast or c-style cast? I don't see how.
    – alfC
    Nov 13 '18 at 3:41


















  • fftw_complex is a typedef of double[2] the problem is that I am reinterpreting from std::complex<double>& to double[2]&. std::complex is indeed now mandated to have double[2] layout, what I don't know if that saves reinterpret_cast from being UB, cppreference seems to say that reinterpret is ok here (at least for refences, doesn't say anything about pointers) en.cppreference.com/w/cpp/numeric/complex.
    – alfC
    Nov 13 '18 at 1:25










  • I am tempted from you answer to say that all the paranoia of std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(in))) can be simply replaced by (fftw_complex*)in, because I am using C-library anyway. Good. (BTW there is no cast to (double*) involved I think.)
    – alfC
    Nov 13 '18 at 1:29












  • It means reinterpret_cast isn't needed at all, because given p = &c[0], p and p + 1 are guaranteed to be addresses of valid doubles and that's all you need (minus casting away the const). I agree that std::launder() seems like overkill and personally I would probably write const_cast<double *>(&c[0][0]) but I see nothing wrong with the C-style cast version.
    – TypeIA
    Nov 13 '18 at 1:43










  • Also maybe worth observing that the layout guarantees of std::vector come into play here too, such that given std::vector<std::complex> v, you can safely assume that the double components of each complex value are all packed at consecutive memory addresses.
    – TypeIA
    Nov 13 '18 at 1:44










  • Thanks, you say that reinterpret_cast is not needed at all, but how would you call fftw_plan_dft_1d on std::vector<std::complex<double>> without using reinterpret_cast or c-style cast? I don't see how.
    – alfC
    Nov 13 '18 at 3:41
















fftw_complex is a typedef of double[2] the problem is that I am reinterpreting from std::complex<double>& to double[2]&. std::complex is indeed now mandated to have double[2] layout, what I don't know if that saves reinterpret_cast from being UB, cppreference seems to say that reinterpret is ok here (at least for refences, doesn't say anything about pointers) en.cppreference.com/w/cpp/numeric/complex.
– alfC
Nov 13 '18 at 1:25




fftw_complex is a typedef of double[2] the problem is that I am reinterpreting from std::complex<double>& to double[2]&. std::complex is indeed now mandated to have double[2] layout, what I don't know if that saves reinterpret_cast from being UB, cppreference seems to say that reinterpret is ok here (at least for refences, doesn't say anything about pointers) en.cppreference.com/w/cpp/numeric/complex.
– alfC
Nov 13 '18 at 1:25












I am tempted from you answer to say that all the paranoia of std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(in))) can be simply replaced by (fftw_complex*)in, because I am using C-library anyway. Good. (BTW there is no cast to (double*) involved I think.)
– alfC
Nov 13 '18 at 1:29






I am tempted from you answer to say that all the paranoia of std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(in))) can be simply replaced by (fftw_complex*)in, because I am using C-library anyway. Good. (BTW there is no cast to (double*) involved I think.)
– alfC
Nov 13 '18 at 1:29














It means reinterpret_cast isn't needed at all, because given p = &c[0], p and p + 1 are guaranteed to be addresses of valid doubles and that's all you need (minus casting away the const). I agree that std::launder() seems like overkill and personally I would probably write const_cast<double *>(&c[0][0]) but I see nothing wrong with the C-style cast version.
– TypeIA
Nov 13 '18 at 1:43




It means reinterpret_cast isn't needed at all, because given p = &c[0], p and p + 1 are guaranteed to be addresses of valid doubles and that's all you need (minus casting away the const). I agree that std::launder() seems like overkill and personally I would probably write const_cast<double *>(&c[0][0]) but I see nothing wrong with the C-style cast version.
– TypeIA
Nov 13 '18 at 1:43












Also maybe worth observing that the layout guarantees of std::vector come into play here too, such that given std::vector<std::complex> v, you can safely assume that the double components of each complex value are all packed at consecutive memory addresses.
– TypeIA
Nov 13 '18 at 1:44




Also maybe worth observing that the layout guarantees of std::vector come into play here too, such that given std::vector<std::complex> v, you can safely assume that the double components of each complex value are all packed at consecutive memory addresses.
– TypeIA
Nov 13 '18 at 1:44












Thanks, you say that reinterpret_cast is not needed at all, but how would you call fftw_plan_dft_1d on std::vector<std::complex<double>> without using reinterpret_cast or c-style cast? I don't see how.
– alfC
Nov 13 '18 at 3:41




Thanks, you say that reinterpret_cast is not needed at all, but how would you call fftw_plan_dft_1d on std::vector<std::complex<double>> without using reinterpret_cast or c-style cast? I don't see how.
– alfC
Nov 13 '18 at 3:41


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53271883%2fproper-way-to-call-a-c-function-taking-non-const-pointer-arguments-const-cast%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Bressuire

Vorschmack

Quarantine