我知道语言规范禁止功能模板的部分特化.
我想知道为什么禁止它的理由?它们没用吗?
template<typename T, typename U> void f() {} //allowed!
template<> void f<int, char>() {} //allowed!
template<typename T> void f<char, T>() {} //not allowed!
template<typename T> void f<T, int>() {} //not allowed!
Run Code Online (Sandbox Code Playgroud) c++ language-design partial-specialization template-specialization function-templates
我知道下面的代码是类的部分特化:
template <typename T1, typename T2>
class MyClass {
…
};
// partial specialization: both template parameters have same type
template <typename T>
class MyClass<T,T> {
…
};
Run Code Online (Sandbox Code Playgroud)
另外我知道C++不允许函数模板部分特化(只允许完整).但是我的代码是否意味着我对一个/同一类型的参数有部分专业的函数模板?因为它适用于Microsoft Visual Studio 2010 Express!如果不是,那么请您解释部分专业化概念吗?
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
template <typename T1, typename T2>
inline T1 max (T1 const& a, T2 const& b)
{
return a < b ? b : a;
}
template <typename T>
inline T const& max (T const& a, T const& b)
{
return …
Run Code Online (Sandbox Code Playgroud) c++ templates partial-specialization template-specialization
假设我已经宣布:
template <typename T> void foo(T& t);
Run Code Online (Sandbox Code Playgroud)
现在,有什么区别
template <> void foo<int>(int& t);
Run Code Online (Sandbox Code Playgroud)
和
template void foo<int>(int& t);
Run Code Online (Sandbox Code Playgroud)
语义?模板与无括号和模板与空括号在其他上下文中有其他语义吗?
我注意到一本教科书,您可以为标准库函数提供自己的实现,例如swap(x,y)
通过函数重载的模板特化.这对于可以从赋值交换以外的其他东西中受益的任何类型都是有用的,STL containers
例如(我已经知道了已经写过的掉期).
我的问题是:
什么更好:模板专业化为您的专业交换实现,或函数重载提供您希望在没有模板的情况下使用的确切参数?
为什么更好?或者如果他们是平等的,为什么呢?
c++ stl overloading standard-library template-specialization
在C++ Primer Plus(2001,捷克语翻译)中,我发现了这些不同的模板特化语法:
功能模板
template <typename T> void foo(T);
Run Code Online (Sandbox Code Playgroud)
专业化语法
void foo(int param); // 1
void foo<int>(int param); // 2
template <> void foo<int>(int param); // 3
template <> void foo(int param); // 4
template void foo(int param); // 5
Run Code Online (Sandbox Code Playgroud)
谷歌搜索了一下,我发现只有3号例子.它们之间是否存在差异(通话,编译,使用)?其中一些是否已过时/弃用?为什么不使用No.1?
考虑以下类模板"X"及其部分特化.
template <class ...Types>
struct X {}; // #1
template <class T1>
struct X<T1> {}; // #2
template <class T1, class ...Types>
struct X<T1, Types...> {}; // #3
X<int> x; // #2 or #3 ?
Run Code Online (Sandbox Code Playgroud)
我怀疑X <int>是不明确的.这是因为:
很明显,#2和#3都比#1更专业,现在比较#2和#3.根据14.5.5.2,让我们考虑以下哪个#2'和#3'更专业.
template <class T1>
void f(X<T1>); // #2'
template <class T1, class ...Types>
void f(X<T1, Types...>); // #3'
Run Code Online (Sandbox Code Playgroud)
根据14.8.2.4,第一步是模板参数推导,使用#2'作为参数模板,#3'作为参数模板.给定唯一的参数类型是X <A1>,推导出的T1是A1,而Types是空的.
A = X<A1>, P = X<T1, Types...> => T1 = A1, Types = {}
Run Code Online (Sandbox Code Playgroud)
第二步是使用#3'作为参数模板,使用#2'作为参数模板.鉴于唯一的参数类型是X <A1,Args ...>,根据14.8.2.5/9(注意该段最近由N3281修订),Args被简单地忽略,推断的T1是A1并且参数推断成功.
A = X<A1, Args...>, P = …
Run Code Online (Sandbox Code Playgroud) c++ templates template-specialization variadic-templates c++11
阅读这个问题让我想知道:是否存在禁止类模板重载的技术原因?
通过重载,我的意思是有几个模板具有相同的名称,但不同的参数,例如
template <typename T>
struct Foo {};
template <typename T1, typename T2>
struct Foo {};
template <unsigned int N>
struct Foo {};
Run Code Online (Sandbox Code Playgroud)
编译器设法处理重载的函数和函数模板,是不是可以将相同的技术(例如名称修改)应用于类模板?
起初,我认为这可能会在单独使用模板标识符时引起一些歧义问题,但唯一可能发生的情况是将其作为模板模板参数传递,因此参数的类型可用于选择合适的超载:
template <template <typename> class T>
void A {};
template <template <unsigned int> class T>
void B {};
A<Foo> a; // resolves to Foo<T>
B<Foo> b; // resolves to Foo<N>
Run Code Online (Sandbox Code Playgroud)
你认为这样的功能有用吗?是否存在一些"好"(即技术)原因,为什么在当前的C++中这是不可能的?
c++ templates overloading template-specialization language-lawyer
在查看文档时std::swap
,我看到了很多专业化.
看起来每个STL容器以及许多其他std工具都有专门的交换.
我想借助模板,我们不需要所有这些专业化?
例如,
如果我自己编写,pair
它可以与模板化版本一起正常工作:
template<class T1,class T2>
struct my_pair{
T1 t1;
T2 t2;
};
int main() {
my_pair<int,char> x{1,'a'};
my_pair<int,char> y{2,'b'};
std::swap(x,y);
}
Run Code Online (Sandbox Code Playgroud)
那么从专业化中获得了什么std::pair
?
template< class T1, class T2 >
void swap( pair<T1,T2>& lhs, pair<T1,T2>& rhs );
Run Code Online (Sandbox Code Playgroud)
我也想知道我是否应该为自定义类编写自己的专业,
或者只是依赖于模板版本.
在当前草案的 17.6.4.2.1/1和17.6.4.2.1/2中,标准限制是针对用户注入的专业化namespace std
.
如果C++程序向命名空间std或命名空间std中的命名空间添加声明或定义,则它是未定义的,除非另有说明.只有当声明取决于用户定义的类型 并且特化符合原始模板的标准库要求且未明确禁止时,程序才可以将任何标准库模板的模板特化添加到命名空间std .
我无法在标准中找到定义用户定义类型的短语.
我听说声称一个选项是一个类型,是不是std::is_fundamental
是一个用户定义类型,在这种情况下std::vector<int>
将是一个用户定义的类型.
另一种答案是用户定义的类型是用户定义的类型.由于用户未定义std::vector<int>
,并且std::vector<int>
不依赖于用户定义的任何类型,std::vector<int>
因此不是用户定义的类型.
一个实际的问题,这影响是"你可以注入一个专业化的std::hash
为std::tuple<Ts...>
成namespace std
如果能够这样做在一定程度上方便-另一种方法是创建另一个命名空间,我们递归构建我们的哈希std::tuple
(可能还有其他类型的std
没有hash
支持),当且仅当我们无法在该命名空间中找到哈希时,我们才会重新开始std
.
但是,如果这是合法的,那么如果标准hash
为std::tuple
to 添加了特殊化namespace std
,那么专用它的代码就会被破坏,从而创建一个不再添加此类特化的理由.
虽然我所说的std::vector<int>
是一个具体的例子,但我试图询问定义的类型std
是否是用户定义的类型.次要问题是,就算没有,也许std::tuple<int>
成为一个用户定义类型用户使用时(这得到滑:那么,什么会发生,如果里面的东西std
定义std::tuple<int>
,你局部专门hash
为 …
假设我是某个模板库(CTL
)的用户,它定义了一个名为的模板,比方说,Hector
template <class T>
class Hector {...};
Run Code Online (Sandbox Code Playgroud)
在其文档中,它提供了许多关于Hector
模板行为的保证.但是它还定义了某种类型的特化Cool
template <>
class Hector<Cool> {....};
Run Code Online (Sandbox Code Playgroud)
专业化的目的是更优化的实现Hector
,但不幸的是,由于这种优化,许多保证Hector
被违反.
目前我真的不需要优化,我宁愿保留所有的保证Hector
.有没有办法,如果不改变库代码(CTL
是一个非常值得尊敬的库,你知道),绕过专业化吗?有什么办法吗?也许写一些包装?什么?我只想让编译器以Hector<Cool>
正常的,非优化的方式生成代码,并提供所有保证.