【问题标题】:sized arrays as function parameter types in C++大小数组作为 C++ 中的函数参数类型
【发布时间】:2011-12-18 23:31:25
【问题描述】:

我正在为我的结构使用模板,例如:

#pragma pack(push, 1)
template <typename T>
struct S
{
   T t;

   inline void Set(const T& val) { t = val; }
}
#pragma pack(pop)

T 可以是 float、int、short 或 char[10]、char[1] 或 char[2](最好是任何长度都可以)。

虽然上面的方法对于整数类型来说效果很好,但我在实现 char[n] 部分时遇到了困难:

  1. 我需要使用 strncpy 或 memcpy 而不是赋值运算符
  2. 使用上述方法,编译器会抱怨签名 (const char[2]& val) 以及我通过 s.Set("T") 调用它。
  3. 具有整数类型和字符类型的 S 之间的接口必须与调用它们的通用代码相同(并且不关心它们是什么类型)。

【问题讨论】:

  • 为什么是char[]s 而不是std::strings?你不会有这些问题。
  • @Mat 它用于打包结构的上下文中,直接放在网络上,不幸的是 std::string 不能用于此目的。
  • 您仍然可以将std::string 用于您的Set 方法。
  • @Mat 不确定我是否在关注。 Set方法中的参数类型不需要和typename T一样吗?
  • @Mat:这不会太短。 Christkirk:是的。看我的回答,你的代码很好。

标签: c++ templates struct arrays


【解决方案1】:

您可以在char[10] 等情况下为T 定义模板专业化。这样做时是否还有问题?但正如 Mat 已经指出的,使用字符串是一种值得考虑的方法。

#include <iostream>

#pragma pack(push, 1)
template <typename T>
struct S
{
   T t;

   inline void Set(const T& val) { std::cout << "general\n"; }
};

template <int len>
struct S<char[len]>
{
   char t[len];

   inline void Set(const std::string& val) { std::cout << "specialization\n"; }
};
#pragma pack(pop)

int main() {

    S<int> a;
    a.Set(10);

    S<char[20]> b;
    b.Set("turkey!");

    return 0;
}

http://codepad.org/X8YVuFja 输出:

一般
专业化

【讨论】:

  • 我想我的问题在于 C++ 模板语法而不是概念。你愿意提供一个这样的专业化的例子吗?
  • @chriskirk:专业化实际上归结为为整数类型编写一次类,为字符数组编写一次。这是可以避免的,但也可以让事情变得更容易。
  • @MooingDuck 是否也可以在 char[n] 类型的所有特化的方法签名中包含 std::string?我认为从最终用户的角度来看,它会更方便一些。
  • @chriskirk:当然。除了完全限定的类名之外,没有什么说特化必须与泛型有任何东西。
  • @MooingDuck 你愿意提供一个例子吗?我确实很感兴趣=)
【解决方案2】:

好吧,部分专业化可能会解决问题:

template <typename T> struct S
{
  T x;
  void set(const T & y) { x = y; }
};

template <typename T, unsigned int N> struct S<T[N]>
{
  T x[N];
  void set(const T (&y)[N]) { std::copy(y, y + N, x); }
};

用法:

S<char[10]> b;
char c[10] = "Hello";
b.set(c);

【讨论】:

    【解决方案3】:

    对我来说很好:http://codepad.org/03FSqZC6

    #pragma pack(push, 1)
    template <typename T>
    struct S
    {
       T t;
    
       inline void Set(const T& val) {}
    };
    #pragma pack(pop)
    
    int main() {
        typedef char (carray)[10];  //do you have a line like this?
        S<carray> lhs;
        carray rhs = "HELLO";
        lhs.Set(rhs);
        return 0;
    }
    

    您的问题很可能是由使用不正确的数组类型引起的。有关正确 typedef 的示例,请参阅我的代码。

    编辑:

    我刚刚意识到,如果您已经拥有 std::string 或任何类型的动态数组,那么调用 Set 会很痛苦。进行模板特化。

    【讨论】:

    • 有趣的方法。我没有按照你概述的方式使用 typedef。
    • 你确定这是在做你认为的事情吗?
    • @KerrekSB:你犯的错误比我少,但根据codepad.org/3DXoBLTf,S、lhs、rhs 和val 的大小都是 10。我想念?
    • 嗯,你的Set 函数目前是空的,所以它肯定没有做正确的事情。问题是,正确的实现应该是什么样子?
    • 这不是(技术上)问题的一部分。 codepad.org/QNW6G8Qx memcpy 有效,但仅适用于 POD 类型。如果他想要非 POD 类型,他将不得不专门化单个与数组。
    猜你喜欢
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    相关资源
    最近更新 更多