C库 - 在C ++中使用:重定义,不同的类型修饰符

时间:2016-07-14 10:10:41

标签: c++ typedef redefinition

我最近在纯C中构建了一个CSV库。 头文件如下所示:

  #ifndef CSV_H
  #define CSV_H

    #include "unicode/ustdio.h"
    #include "unicode/uchar.h"
    #include "unicode/ucsdet.h"
    #include "unicode/ustring.h"

    #define T CSV_T
    typedef struct T *T;

    extern T    CSV_new(char *filename);
    extern void CSV_free(T *csv);
    extern int  CSV_length(T csv);
    extern void CSV_print_info(T csv);
    extern UChar **CSV_get_header(T csv);
    extern UChar ***CSV_get_values(T csv);
    extern long CSV_get_num_columns(T csv);
    extern long CSV_get_num_lines(T csv);
    extern char *CSV_get_charset(T csv);

    #undef T
    #endif

struct CSV_T的实际定义在代码文件中完成,以隐藏实现。我经常在使用纯C的不同项目中使用该库,没问题。现在我想在使用C ++构建的GUI应用程序中重用代码,并收到以下错误消息:

Error   C2373   'CSV_T': redefinition; different type modifiers     ... xxx\Projects\LibCSV\LibCSV\csv.h    10  

C ++是否处理了与C不同的typedef?以某种方式混淆,......

2 个答案:

答案 0 :(得分:5)

Here是你的MCVE应该是什么样的:

typedef struct T *T;

这是一个完整的单行源文件,可以重现该问题并且没有依赖关系。没有宏,没有标题,没有不必要的代码。

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:1:19: error: conflicting declaration 'typedef struct T* T'
 typedef struct T *T;
                   ^
main.cpp:1:16: note: previous declaration as 'struct T'
 typedef struct T *T;
            ^

它在C中起作用的原因是T不是结构的名称;你需要struct前缀。

在C ++中,情况并非如此,因为首先不需要struct前缀。一旦你声明T是一个类(令人困惑的是,你在typedef本身!),你不能只提供其他类型(你正在尝试的那个)使用typedef创建相同的名称。

无论如何,你正在做的事情相当奇怪,让CSV_T意味着struct CSV_T*。我建议不要这样做。

如果您只是坚持使用typedef struct CSV_T CSV_T,那么这将适用于两种语言,但尝试使用相同名称创建不同的类型是不可行的。< / p>

答案 1 :(得分:4)

C ++标准的附录C说:

  

7.1.3

     

更改: C ++ typedef名称必须与同一作用域中声明的任何类类型名称不同(除非typedef是具有相同名称的类名的同义词)。在C中,在同一范围内声明的typedef名称和结构标记名称可以具有相同的名称(因为它们具有不同的名称空间)。

     

示例:

typedef struct name1 { /.../ } name1; // valid C and C++
struct name { /.../ };
typedef int name; // valid C, invalid C++
     

基本原理:为了便于使用,在对象声明或类型转换中使用时,C ++不要求类型名称以关键字class,struct或union作为前缀。

     

示例:

 class name { /.../ };
 name i; // i has type class name
     

对原始功能的影响:删除语义定义明确的功能。

     

难以转换:语义转换。必须重命名两种类型中的一种。

     

使用范围广泛:很少。