Cast between const char* [][3] and std::array< const char*, 3 >*

大憨熊 提交于 2019-12-23 10:54:06

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!