【问题标题】:Cast between const char* [][3] and std::array< const char*, 3 >*在 const char* [][3] 和 std::array< const char*, 3 >* 之间转换
【发布时间】:2014-05-05 11:35:46
【问题描述】:

我需要一种在这两种类型的变量之间进行转换的方法:

std::array< const char*, 3 >* foo;
const char* foo[][3];

因为我需要能够将两种类型都传递给函数。该函数可以通过以下任何一种方式定义,以使转换更容易为准:

void bar( std::array< const char*, 3 >* param );
void bar( const char* param[][3] );

this 问题中,Jarod42 建议使用here 方法。有没有更清洁的方法来做到这一点?

编辑回复dyplink

这个reinterpret_cast 确实对我有用,但Ivan Shcherbakov 将其描述为“丑陋的肮脏黑客”我已将代码粘贴在下面......我不明白为什么这是一个黑客,或者为什么会出错吗? Nathan Monteleone建议的模板方法一定比这个好吗?

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 );
}

【问题讨论】:

  • 我们可以知道您要在foo 中存储什么吗?
  • 我很确定这是重复的.. std::array 的大小和对齐方式未指定 AFAIK,因此 std::array&lt;X,Y&gt;*X (*arr)[Y] 不兼容
  • 您说函数可以通过其中任何一种方式定义,但必须以其中一种方式定义?使用 template&lt;class I&gt; void bar(I start, I end),您可以将迭代器传递给这些容器中的任何一个,或者实际上是任何标准容器或 c 样式数组,或者只是容器的一部分。
  • dyp,我认为关键是没有指定对齐方式,是的,两个版本的 foo 应该完全兼容。黑色,该变量将包含 3 个动态分配的 c 字符串数组。

标签: c++ arrays dynamic-arrays


【解决方案1】:

在我的脑海中,你能做的最简单最优雅的事情就是让你的 bar 函数成为一个模板。

template <class T> void Tbar( T param ) {
    char c12 = param[1][2];    // (for example)
}

当然,此时您将失去强制其大小为 [3] 的能力。因此,您可以执行以下操作,例如将模板实现隐藏在源文件中,将两个原始函数作为原型公开在标头中,然后在 cpp 文件中实现为

void bar( std::array< const char*, 3 >* param ) { Tbar(param); }
void bar( const char* param[][3] ) { Tbar(param); }

这种方法的优点是它完全避免了强制转换。我想,缺点是你在 Tbar 中可以做的事情有点受限,即你被限制在 char*[][3]array&lt;char*, 3&gt;* 的任何共同操作上。例如,如果 Tbar 是非模板类中的设置器,则存储指向数组的指针也将更加困难。

【讨论】:

  • 我想我可以用extents 做一个static_assert 以确保大小为3,对吧?然后我应该能够继续进行统一实例化。
  • @JonathanMee 你也许可以。实际上我以前从未使用过std::extent,所以想知道你是否成功了。
  • Nathan Monteleone 嗯,我的成功比我希望的要少。我在 std::array 和 C 样式数组上使用 std::extent 时遇到问题。根据 Ivan Shcherbakov 的说法,我想完成这项工作,因为如果我不这样做,我就是一个坏人。为此,我创建了一个新问题:stackoverflow.com/questions/22712965/…
【解决方案2】:

基于Nathan Monteleone的解决方案:

template<typename T>
enable_if_t<conditional_t<is_array_v<T>, extent<T>, tuple_size<T>>::value == 3U> bar(T* param){}

我相信这个解决方案是世界上最好的,因为它避免了依赖于实现的reinterpret_cast。并且它强制 param 在编译时的大小必须为 3。

请注意,conditional_t 的值仅在选择类型后才会调用。有关更多信息,请参阅:Short Circuiting Operators in an enable_if

Live Example

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    • 2013-04-23
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 2018-08-23
    • 1970-01-01
    相关资源
    最近更新 更多