问题
I need a way to cast between these two types of variables:
std::array< const char*, 3 >* foo;
const char* foo[][3];
Because I need to be able to pass both types to a function. The function can be defined either of these ways, whichever makes conversion easier:
void bar( std::array< const char*, 3 >* param );
void bar( const char* param[][3] );
In this question, Jarod42 suggests using the method here. Is there a cleaner way to do this?
Edit in response to dyp's link
This reinterpret_cast
did work for me, but Ivan Shcherbakov describes it as an "ugly dirty hack" I've pasted the code, below... I don't understand why this is a hack, or why something could go wrong with it? Is the template method suggested by Nathan Monteleone necessarily better than this?
void bar( std::array< const char*, 3 >* param ){}
void main( void )
{
static const char* cStyle[][3] = { NULL };
std::array< const char*, 3 > foo = { NULL };
std::array< const char*, 3 >* stlStyle = &foo;
bar( reinterpret_cast< std::array< const char*, 3 >* >( cStyle ) );
bar( stlStyle );
}
回答1:
Off the top of my head, the easiest most elegant thing you could do is just make your bar function a template.
template <class T> void Tbar( T param ) {
char c12 = param[1][2]; // (for example)
}
Of course at that point you lose the ability to enforce that it be of size [3]. So you could do something like hide the template implementation down in a source file, expose both of your original functions as prototypes in a header, and in the cpp file just implement as
void bar( std::array< const char*, 3 >* param ) { Tbar(param); }
void bar( const char* param[][3] ) { Tbar(param); }
The advantage of this sort of approach is that it avoids casting entirely. The disadvantage, I suppose, is that you're a little bit more limited in what you can do inside Tbar, namely you're restricted to whatever operations both char*[][3]
and array<char*, 3>*
have in common. It would also be harder to store off a pointer to the array if, for example, Tbar was a setter in a non-template class.
回答2:
Based on Nathan Monteleone's solution:
template<typename T>
enable_if_t<conditional_t<is_array_v<T>, extent<T>, tuple_size<T>>::value == 3U> bar(T* param){}
I believe this solution is the best of all worlds, cause it avoids the reinterpret_cast
that is implementation dependent. And it enforces that param
must be of size 3 at compile time.
Note that the conditional_t
's value is called only after a type is selected. For more on this see: Short Circuiting Operators in an enable_if
Live Example
来源:https://stackoverflow.com/questions/22671635/cast-between-const-char-3-and-stdarray-const-char-3