本系列文章从零开始介绍C++模版元编程,需要有C++基础。
函数模版
template <typename T>
T add(T const a, T const b) {
return a + b;
}
auto a = add(42, 21);
auto d = add<double>(41.0, 21); // 无法自动推导类型的时候可以显示的指定类型
类模版
template <typename T>
class wrapper {
public:
wrapper(T const v) : value(v) {}
T const& get() const { return value; }
private:
T value;
};
wrapper a(1); // 模版参数推导
wrapper<int> b(2);
成员函数模版
模版类的成员函数
template <typename T>
class comoosition {
public:
T add(T const a, T const b) {
return a + b;
}
};
composition<int> c;
c.add(12,32);
非模版类的成员函数模版
class compotion {
public:
template <typename T>
T add(T const a, T const b) {
return a + b;
}
};
compostion c;
c.add<int>(12,13);
c.add(1,2);
类模版的成员函数模版
template <typename T>
class wrapper {
pbulic:
wrapper(T const v) : value(v) {}
T const& get() const { return value; }
template <typename U>
U as() const {
return static_cast<U>(value);
}
private:
T value;
};
// 成员函数模板的模板形参必须与类模板的模板形参不同
wrapper<double> a(42.1);
auto d = a.get();
auto b = a.as<int>();
模版参数
类型模版参数
template <typename T> // 不带默认参数
class wrapper {};
template <typename T = int> // 带默认参数
class wrapper {};
template <typename... T> // 可变参数模版
class wrapper {};
非类型模版
template <int V>
class foo {};
template <int V = 42>
class foo {};
template <int... V>
class foo {};
template <typename T, size_t S>
class buffer {
T data_[S];
public:
constexpr T const * data() const { return data_; }
constexpr T& operator[](size_t const index) {
return data_[index];
}
constexpr T const& operator[] (size_t const index) const {
return data_[index];
}
};
buffer<int, 10> b1;
buffer<int, 2*5> b2;
看一种更常见的类型
struct device {
virtual void output() = 0;
virtual ~device() {}
};
template <void (*action) ()>
struct smart_device : device {
void output() override {
(*action) ();
}
};
void say_hello_in_english() {
std::cout << "Hello, world!\n";
}
auto w1 = std::make_unique<smart_device<&say_hello_in_english>>();
w1->output();
双重模版参数
template <typename T>
class simple_wrapper {
public:
T value;
};
template <typename T>
class fancy_wrapper {
public:
fancy_wrapper(T const v) :value(v) {}
T const& get() const { return value; }
template <typename U> U as() const {
return static_cast<U>(value);
}
private:
T value;
};
template <typename T, typename U, template<typename> typename W = fancy_wrapper>
class wrapping_pair {
public:
wrapping_pair(T const a, U const b) : item1(a), item2(b) { }
W<T> item1;
W<U> item2;
};
默认模版参数
template <typename T = int>
class foo { /*...*/ };
template <typename T = int, typename U = double>
class bar { /*...*/ };
template <typename T = int, typename U>
class bar { }; // error, 类模版带默认参数的参数,后面不能跟不带默认参数的参数。
template <typename T = int, typename U>
void func() {} // OK
template <typename T = int>
struct foo;
template <typename T = int> // error redefinition // of default parameter
struct foo {};
模版实例化
模版实例化可以是显式的也可以是隐式的。
隐式实例化
template <typename T>
struct foo {
void f() {}
};
int main() {
foo<int> *x; // 不会实例化
foo<int> p; // 会
foo<int> p1; // 会
foo<double> *q; // 不会
return 0;
}
template <typename T>
struct foo {
static T data;
};
template <typename T> T foo<T>::data = 0;
int main() {
foo<int> a;
foo<double> b;
foo<double> c;
std::cout << a.data << '\n'; // 0
std::cout << b.data << '\n'; // 0
std::cout << c.data << '\n'; // 0
b.data = 42;
std::cout << a.data << '\n'; // 0
std::cout << b.data << '\n'; // 42
std::cout << c.data << '\n'; // 42
}
显示实例化
显示实例化分为显示实例化定义和显示实例化声明。
// 类模版
template class-key template-name <argument-list>
// 函数模版
template return-type name<argument-list> (parameter-list);
template return-type name(parameter-list);
namespace ns {
template <typename T>
struct wrapper {
T value;
};
template struct wrapper<int>; // 显示实例化
}
template struct ns::wrapper<double>; // 显示实例化
int main() {
}
namespace ns {
template <typename T>
T add(T const a, T const b) {
return a + b;
}
template int add(int, int);
}
template double ns::add(double, double);
标签:00,const,模版,c++,wrapper,template,foo,class
From: https://www.cnblogs.com/Heoric/p/17440697.html