模板函数参数中的自动模板专业化
Automatic Template Specialization in Template Function Argument
我遇到了以下问题(下面的代码):
template<class T>
void printname(const T& t){std::cout<<t<<std::endl;}
template<class T>
void applyfunc(const T& t, void (*f)(const T& )){(*f)(t);}
int main(){
const int a=1;
applyfunc(a,printname);
getchar();
return 0;
}
我的问题是,它使用vc++8(VS2005)和GCC、CLang(在Ubuntu 12.04上)进行编译但未能使用vc++2008express进行编译。
这似乎是法律法规,但我真的不明白为什么。
如果有人能解释,我将不胜感激。
假设它是合法的,有什么方法可以对函子做类似的事情吗?
我认为您打算将func
用于printname
(反之亦然)。
值得一提的是,我相信这段代码是合法的,而VS2008(还有VS2010;我现在没有VS2012)拒绝它的事实看起来像是一个编译器错误。
回复:与函子类似的东西-看看这是否对你有用:
#include <iostream>
struct printname {
template<class T>
void operator()(const T& t) { std::cout<<t<<std::endl; }
};
template<class T, class F>
void applyfunc(const T& t, F f) { f(t); }
int main(){
const int a=1;
applyfunc(a, printname());
return 0;
}
我不确定问题是为什么它在大多数编译器中都能工作,还是为什么它在VS2008中失败。如果问题是前者,我们可以讨论一个简化版本:
template <typename T>
void f(T const &) {}
void g(void (*fn)(std::string const&) {}
g(f); // compiles
void (*fn)(double const &) = f;
函数的指针在语言中有点特殊,因为相同的名称可以指代不同的重载。当在代码中使用函数的名称时,编译器无法确定哪些重载是由自己决定的,因此它将使用表达式的目标来确定这一点。在g(f)
的情况下,由于g
函数采用void (std::string const&)
类型的函数,它将把f
解析为f<std::string>
,而在初始化fn
的情况下编译器将解析为专用f<double>
。
请注意,这是语言中非常常用的功能:
std::cout << std::endl;
名称std::endl
指的是一个模板:
template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);
编译器发现这是在类型为basic_ostream<char,char_traits<char>>
的对象std::cout
上调用的,并且唯一与对operator<<
的调用匹配的专门化是charT == char
和traits == char_traits<char>
所在的专门化,并选择正确的专门化。
在Visual Studio 2010上,该解决方案简单而微妙。您只需在applyfunc(a,printname<int>);
行的printname之后添加<int>
即可。编译器需要帮助确定要使用的模板类型。
#include <iostream>
struct printname
{
template<class T>
void operator()(const T& t)
{
std::cout << t << std::endl;
}
};
template<class T, class F>
void applyfunc(const T& t, F f)
{
f(t);
}
int main()
{
const int a=1;
applyfunc(a, printname<int>); // Add <int> here
return 0;
}
- 函数模板部分专业化-有什么解决方法吗
- 我应该声明我的函数模板专业化还是定义它们就足够了
- std::转换move构造函数的模板专业化的变体
- 常量函数参数的专业化
- 纯虚函数的模板专业化
- 删除模板函数,除了它的一个专业化
- 为什么这不是函数模板的部分专业化
- 在允许的函数模板的明确专业化中扣除了多个模板参数
- 使用声明类型选择函数专业化
- 关于函数的完整专业化的名称查找的漫画
- C - 具有非类型模板参数的模板类上的专业化函数模板
- C++11性能:Lambda内联与函数模板专业化
- 为什么不允许对成员函数的模板专业化
- 成员函数模板参数的部分专业化
- C 将lambda函数用作模板功能专业化
- 对于需要其他模板参数的类型函数的部分模板专业化
- 特定成员函数的部分专业化
- 指针作为函数返回类型的部分专业化
- 为什么未经声明未从.cpp文件拾取模板函数的完整专业化
- 实例化错误后成员函数模板的专业化,以及成员函数的顺序