09 模板实战

2021-05-27  本文已影响0人  奇点创客

链接错误

// basics/myfirst.hpp

#ifndef MYFIRST_HPP
#define MYFIRST_HPP

template<typename T>
void printTypeof(const T&);

#endif   // MYFIRST_HPP


// basics/myfirst.cpp

#include "myfirst.hpp"
#include <iostream>

template<typename T>
void printTypeof(const T& x)
{
  std::cout << typeid(x).name() << '\n';
}

// basics/myfirstmain.cpp

#include "myfirst.hpp"

int main()
{
  double pi = 3.14;
  print_typeof(pi); // 为double类型调用函数模板
}

包含模型

// basics/myfirst2.hpp

#ifndef MYFIRST_HPP
#define MYFIRST_HPP

#include <iostream>

template<typename T>
void printTypeof(const T&);

template<typename T>
void printTypeof(const T& x)
{
  std::cout << typeid(x).name() << '\n';
}

#endif   //MYFIRST_HPP

分离模型(已废弃)

// 头文件
#ifndef MYFIRST_HPP
#define MYFIRST_HPP

export template<typename T>
void f(const T&);

#endif

显式实例化(explicit instantiation)

template<typename T>
void f(T) {}

template void f<int>(int); // 实例化f<int>(int),无实参推断
template void f<>(float); // 实例化f<float>(float),有实参推断
template void f(long); // 实例化f<long>(long),有实参推断
extern template void f<int>(int); // 声明但不定义
template<typename T>
class A {
 public:
  void f() {}
};

template class A<void>; // 同时显式实例化template void A<void>::f()
template void A<int>::f(); // 仅显式实例化该成员
template<typename T>
void f() {}

template void f<int>(); // 显式实例化

template<> // 错误:已经基于int实例化过,不能再对int特化
void f<int>()
{
  std::cout << 1;
}
#include <iostream>

template<typename T>
void f()
{}

template<>
void f<int>()
{
  std::cout << 1;
}

template void f<int>(); // 显式实例化的是特化的定义

int main()
{
  f<int>(); // 1
}
template<typename T>
void f(T, T) {}

template void f<double>(double, double); // 显式实例化

f(1, 3.14); // 错误:推断类型不一致,不存在可匹配的普通函数void f(double, double)
f<double>(1, 3.14); // OK

整合包含模型和显式实例化

// stack.hpp
#ifndef STACK_HPP
#define STACK_HPP

#include <vector>

template<typename T>
class Stack {
 public:
  Stack();
  void push(const T&);
  void pop();
  T top() const;
 private:
  std::vector<T> elems;
};

#endif
// stackdef.hpp
#ifndef STACKDEF_HPP
#define STACKDEF_HPP

#include "stack.hpp"
#include <cassert>

template<typename T>
void Stack<T>::push(const T& elem)
{
  elems.push_back(elem);
}

template<typename T>
void Stack<T>::pop()
{
  assert(!elems.empty());
  elems.pop_back();
}

template<typename T>
T Stack<T>::top() const
{
  assert(!elems.empty());
  return elems.back();
}

#endif
#include <iostream>
#include <string>
#include "stackdef.hpp"

int main()
{
  Stack<int> intStack;
  intStack.push(42);
  std::cout << intStack.top() << std::endl;
  intStack.pop();

  Stack<std::string> stringStack;
  stringStack.push("hello");
  std::cout << stringStack.top() << std::endl;
  stringStack.pop();
}
// stack_inst.cpp
#include "stackdef.hpp"
#include <string>

// instantiate class Stack<> for int
template class Stack<int>;

// instantiate member functions of Stack<> for strings
template Stack<std::string>::Stack();
template void Stack<std::string>::push(std::string const&);
template std::string Stack<std::string>::top() const;
#include <iostream>
#include <string>
#include "stack.hpp"

int main()
{
  Stack<int> intStack;
  intStack.push(42);
  std::cout << intStack.top() << std::endl;
  intStack.pop();

  Stack<std::string> stringStack;
  stringStack.push("hello");
  std::cout << stringStack.top() << std::endl;
  stringStack.pop(); // 错误:没有显式实例化std::string版本的此函数
}

使用显式实例化声明

// t.hpp:
template<typename T> void f() {}

extern template void f<int>(); // 声明但不定义
extern template void f<float>(); // 声明但不定义

// t.cpp:
template void f<int>(); // 定义
template void f<float>(); // 定义

内联

template<typename T>
inline T min(const T&, const T&);

预编译头文件

在Visual Studio中使用预编译头

#pragma once
#include <vector>
#include <string>
#include "stdafx.h"

[图片上传失败...(image-3a288e-1622076841733)]

// file "test.cpp"
#include "stdafx.h" // 相当于在test.h中包含了stdafx.h中的所有头文件
上一篇下一篇

猜你喜欢

热点阅读