C++模版使用技巧--Int2Type

本文深入探讨了C++模板的几种高级用法,包括如何利用模板特性实现Int2Type转换,以及如何根据条件选择不同类型的实例化过程。通过具体实例展示了模板在运行时和编译时的不同行为。

C++模版使用技巧--Int2Type

一  Int2Type
平常我们所看到的int是一个类型,例如1,2,3...等属于int。 但是这里说的是通过模版使每一个int类型变量都当成是不同的类型。
二 C++模版的迟绑定
这个名字是我起的,因为不知道正式的称呼是什么,意思是说在使用C++的模版的时候,只有在你的代码里面调用了某个模版方法,在编译的时候才会产生对应的方法,也即编译后的代码中不包含我们没有使用的模版方法。看下面的实例是可以编译运行的:
class X {
public:
 
void f() {}
}
;

class Y {
public:
 
void g() {}
}
;

template
< typename T >   class Z {
  T t;
public:
 
void a() { t.f(); }
 
void b() { t.g(); }
}
;

int main() {
  Z
<X> zx;
  zx.a();
// Doesn't create Z<X>::b()
  Z<Y> zy;
  zy.b();
// Doesn't create Z<Y>::a()
}
  ///:~

三 问题

template < typename T, bool isPolymorphic >
class NiftyContainer
{  
  
void DoSomething()
  
{
      T
* pSomeObj = ;
     
if (isPolymorphic)
     
{
         T
* pNewObj = pSomeObj->Clone();
 
      }

     
else
     
{
         T
* pNewObj = new T(*pSomeObj);
        
      }

   }

}
;
class Test
{
public:
    Test()
{};
}
;

void main()
{
    NiftyContainer
<Test,true> test;
   
//test.DoSomething(); // 这里通不过编译
   
}
大家也许会说上面的方法代码没有问题,我说,有问题,仔细看一开始的代码和我的说明,我说的是只要我们的代码里面用到模版方法就会被编译为目标代码,而不是说在代码运行的时候使用到的代码才会被编译为目标代码,好的,搞清楚了这个就可以知道上面的实例为什么通不过编译了。
四 Int2Type
下面正式进入主题Int2Type的作用和使用,上面的实例,我们传入的T类型中只有clone或public构造函数中的一个,我们想根据bool值来选择使用clone或new,但是上面的代码有问题,编译都不过偶,下面使用Int2Type来实现:

template < int v >
struct Int2Type
{
  
enum { value = v };
}
;


template
< typename T, bool isPolymorphic >
class NiftyContainer
{
private:
  
void DoSomething(T* pObj, Int2Type<true>)
  
{
      T
* pNewObj = pObj->Clone();
   
   }

  
void DoSomething(T* pObj, Int2Type<false>)
  
{
      T
* pNewObj = new T(*pObj);
     
   }

public:
  
void DoSomething(T* pObj)
  
{
      DoSomething(pObj, Int2Type
<isPolymorphic>());
   }

}
;
class Test
{
public:
    Test()
{};
}
;
void main()
{
    NiftyContainer
<Test,false> test; //如果用ture不会通过编译
    Test* t = new Test();
    test.DoSomething(t);
}

看了上面的代码,我不禁要再次的赞叹《C++设计新思维》的作者,高!
missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int syntax error: missing ';' before '}' missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int syntax error: missing ';' before '}' missing type specifier - int assumed. Note: C++ does not support default-int syntax error: '}' missing type specifier - int assumed. Note: C++ does not support default-int 'int None': redefinition missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int syntax error: missing ';' before '}' missing type specifier - int assumed. Note: C++ does not support default-int syntax error: '}' syntax error: 'public' missing type specifier - int assumed. Note: C++ does not support default-int syntax error: missing ';' before identifier 'Show' syntax error: 'const' missing type specifier - int assumed. Note: C++ does not support default-int 'int DialogResult': redefinition syntax error: missing ';' before identifier 'Show' syntax error: 'const' missing type specifier - int assumed. Note: C++ does not support default-int 'int DialogResult': redefinition syntax error: missing ';' before identifier 'Show' syntax error: 'const' syntax error: 'private' 'MessageBoxButtons': undeclared identifier syntax error: missing ')' before identifier 'buttons' 'MessageBoxIcon': undeclared identifier syntax error: missing ')' before identifier 'icon' missing type specifier - int assumed. Note: C++ does not support default-int 'int DialogResult': redefinition syntax error: missing ';' before identifier 'ConvertResult' type 'int' unexpected syntax error: '}' syntax error: missing ';' before '}' syntax error: '}' syntax error: missing ';' before '}' The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int syntax error: missing ';' before '}' missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int syntax error: missing ';' before '}' missing type specifier - int assumed. Note: C++ does not support default-int syntax error: '}' missing type specifier - int assumed. Note: C++ does not support default-int 'int None': redefinition missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int missing type specifier - int assumed. Note: C++ does not support default-int syntax error: missing ';' before '}' missing type specifier - int assumed. Note: C++ does not support default-int syntax error: '}' syntax error: 'public' missing type specifier - int assumed. Note: C++ does not support default-int syntax error: missing ';' before identifier 'Show' syntax error: 'const' missing type specifier - int assumed. Note: C++ does not support default-int 'int DialogResult': redefinition syntax error: missing ';' before identifier 'Show' syntax error: 'const' missing type specifier - int assumed. Note: C++ does not support default-int 'int DialogResult': redefinition syntax error: missing ';' before identifier 'Show' syntax error: 'const' syntax error: 'private' 'MessageBoxButtons': undeclared identifier syntax error: missing ')' before identifier 'buttons' 'MessageBoxIcon': undeclared identifier syntax error: missing ')' before identifier 'icon' missing type specifier - int assumed. Note: C++ does not support default-int 'int DialogResult': redefinition syntax error: missing ';' before identifier 'ConvertResult' type 'int' unexpected syntax error: '}' syntax error: missing ';' before '}' syntax error: '}' syntax error: missing ';' before '}'
最新发布
09-29
<think>我们正在处理一个关于C++编译错误的问题,特别是与Windows头文件相关的问题。用户提供了两个引用,其中引用[1]显示的错误包括: - error C2065: 'SOCKET' : undeclared identifier - error C2146: syntax error : missing ';' before identifier 'fd' - error C4430: missing type specifier - int assumed. Note: C++ does not support default-int - 等等 引用[2]则提到了一个类似的错误:syntax error : missing ';' before 'type',并提到可能是由于变量声明的位置问题(在C语言中变量声明必须放在块的开头,而C++允许在任意位置,但这里可能是其他原因)。 用户的问题可以概括为:如何解决包含Windows头文件的C++代码中出现的编译错误,如missing type specifier、syntax error、redefinition等。 根据经验,这些错误通常发生在使用Windows Sockets时,特别是因为`SOCKET`类型定义在`winsock2.h`中。常见的错误原因和解决方案包括: 1. 头文件包含顺序问题:如果包含了`windows.h`,它可能会包含旧版本的`winsock.h`,而我们需要使用`winsock2.h`。因此,正确的做法是在包含`windows.h`之前先定义`WIN32_LEAN_AND_MEAN`,并且确保`winsock2.h`在`windows.h`之前包含,或者至少避免`winsock.h`被包含。 2. 未包含必要的头文件:例如,使用`SOCKET`类型需要包含`winsock2.h`。 3. 多个头文件定义了相同的类型或宏,导致重定义(redefinition)错误。 4. 在C++中,如果类型没有指定,编译器会尝试使用int,但C++不支持默认int,因此会出现C4430错误。 针对引用[1]中的错误,具体分析: - 错误发生在`mysql_com.h`中,这个头文件是MySQL连接器的一部分。错误信息指出在`mysql_com.h`的第183行,有标识符`fd`前面缺少分号,并且缺少类型说明符(默认为int,但C++不支持)。 - 查看MySQL头文件,我们发现它可能使用了`SOCKET`类型,而这个类型通常由Windows Sockets定义。因此,很可能是在包含`mysql_com.h`之前没有正确包含`winsock2.h`。 解决方案步骤: 1. 确保在包含任何可能引用Windows Sockets的头文件(包括MySQL头文件)之前,先包含`winsock2.h`。 2. 使用预编译指令来防止`windows.h`包含`winsock.h`。我们可以定义`WIN32_LEAN_AND_MEAN`来避免包含一些不常用的头文件,从而避免冲突。 3. 注意头文件的包含顺序:先包含`winsock2.h`,再包含`windows.h`,最后包含其他头文件(如MySQL头文件)。 4. 如果还有重定义错误,可能是因为`winsock2.h`和`winsock.h`冲突,确保不要混合使用。 此外,引用[2]中提到的错误“missing ';' before 'type'”可能是由于在函数中间声明变量(在C语言中不允许,但在C++中允许),但这里更可能是由于类型未定义导致编译器无法识别类型,从而将变量名当作其他东西。 因此,我们给出以下解决方案: 步骤1:在包含Windows头文件之前,先定义`WIN32_LEAN_AND_MEAN`,并包含`winsock2.h`。 例如: ```cpp #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #include <windows.h> ``` 步骤2:在包含MySQL头文件之前,确保已经包含了`winsock2.h`。 步骤3:如果有多个源文件,确保在所有需要的地方都按照这个顺序包含。 步骤4:如果问题仍然存在,检查是否在其他地方包含了`winsock.h`,如果有,应该移除并用`winsock2.h`替代。 步骤5:如果MySQL头文件要求特定的包含顺序,可以尝试在包含MySQL头文件之前包含`winsock2.h`,之后不要再包含其他可能引起冲突的头文件。 另外,关于重定义错误,可能是因为同一个头文件被多次包含,可以使用预编译指令(#ifndef, #define, #endif)来防止重复包含。 下面是一个示例代码结构: ```cpp // 防止重复包含的宏定义,通常每个头文件都有,但这里在源文件中我们主要控制包含顺序 #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #include <windows.h> // 然后包含其他系统头文件 // 现在包含MySQL头文件 #include <mysql.h> // 或者具体的mysql_com.h等 // 其他头文件 ``` 如果问题依然存在,可能是因为MySQL的版本与Windows Sockets版本不兼容。可以尝试查看MySQL文档或头文件中的条件编译部分,看是否有需要定义的宏。 根据上述分析,我们给出一个综合解决方案。 注意:用户提到的是在包含Windows头文件时出现的问题,所以我们重点解决头文件依赖和顺序问题。 下面我们将逐步解释如何解决。 </think>### 解决Windows头文件引入的C++编译错误 您在包含Windows头文件时遇到的编译错误(如`missing type specifier`, `syntax error`, `redefinition`)通常是由**头文件包含顺序冲突**或**类型定义缺失**引起的。以下是系统解决方案: #### 1. 解决SOCKET类型未定义错误(关键) ```cpp // 在包含任何Windows头文件前添加👇 #define WIN32_LEAN_AND_MEAN // 禁用无关组件 #include <winsock2.h> // 必须在windows.h前包含! #include <windows.h> ``` - **原理**:`windows.h`默认包含旧版`winsock.h`,而MySQL等库需要新版`winsock2.h`定义的`SOCKET`类型[^1] - **错误原因**:若顺序颠倒,编译器无法识别`SOCKET`类型,导致: - `undeclared identifier`(未声明标识符) - `missing ';' before identifier`(缺少分号) - `missing type specifier - int assumed`(类型推断失败) #### 2. 处理重定义错误(redefinition) ```cpp // 在公共头文件中添加防护宏 #ifndef MY_HEADER_H #define MY_HEADER_H // 头文件内容... #endif ``` - **典型场景**:当`windows.h`和`winsock2.h`被多次包含时,会导致类型重复定义 - **解决方案**: ```cpp #pragma once // 现代编译器支持的单包含指令 #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #include <windows.h> ``` #### 3. 完整解决方案模板 ```cpp // main.cpp #define WIN32_LEAN_AND_MEAN // 步骤1:精简Windows头文件 #define _WINSOCK_DEPRECATED_NO_WARNINGS // 禁用弃用警告 #include <winsock2.h> // 步骤2:优先包含winsock2 #include <windows.h> // 步骤3:再包含windows.h // 最后包含第三方库头文件(如MySQL) #include <mysql.h> int main() { SOCKET s; // 此时SOCKET类型已正确定义 // ... } ``` #### 4. 其他注意事项 - **编译参数**:在VS中添加链接器参数`-lws2_32`(项目属性 → 链接器 → 输入 → 附加依赖项) - **C++标准**:确保项目设置为C++11或更高(避免C风格默认int类型推断) - **头文件冲突**:若仍有错误,检查第三方库是否有兼容Windows的编译宏 > 通过规范头文件包含顺序和预定义宏,可解决90%由Windows头文件引起的编译错误。MySQL等数据库驱动对网络类型依赖较强,必须确保`winsock2.h`优先加载[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值