我最近遇到的代码看起来像这样
template <typename T>
void Foo()
{
T::Bar();
}
我很困惑,这是怎么编的?在C#泛型中对T没有约束。
我意识到模板不像泛型,因为前者基本上是美化的宏,所以就是这样的情况就是Foo
的每个用法都是针对该实例中提供的T
进行编译的,并且给出了它有Bar()
功能吗?有点像鸭子打字?
这是自c ++ 03以来它是如何工作的,还是c ++ 11中的新东西?
答案 0 :(得分:3)
这个模板函数只强制在替换类型T时,表达式T::Bar();
是有效的,只要它有效,它就会编译(在C ++中没有类似C#的约束):
以下是使用模板的两个示例:
#include <iostream>
#include <functional>
struct X
{
static void Bar() { std::cout << "Bar X\n!"; }
};
struct Y
{
static std::function<void(void)> Bar;
};
std::function<void(void)> Y::Bar = []() { std::cout << "Bar Y!"; };
template <typename T>
void Foo()
{
T::Bar();
}
int main()
{
Foo<X>();
Foo<Y>();
return 0;
}
答案 1 :(得分:2)
模板仅在实例化时编译,即通过执行
Foo<int>();
在这种情况下,通过用T
替换你传入的具体类型来生成实际代码(这当然会导致编译错误,因为int
没有静态成员函数{{ 1}})。
这是设计上的,并且一直存在。
答案 2 :(得分:2)
这就是模板的工作方式和工作方式,C ++ 11中没有什么新东西。如果T::Bar()
对于给定类型有效,它会编译,所以它就像你说的那样打字。大多数C ++标准库基于这个原理工作 - 例如迭代器需要operator*
才能工作,如果你有自己的迭代器,它们将使用标准算法,前提是你实现了这个操作符(以及基于迭代器类别所需的其他操作)。您不需要以任何其他方式指定迭代器 - 只需提供所需的操作。