0

我想出了以下问题(下面的代码):

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++ 2008 express 编译。

这似乎是合法的代码,但我真的不明白为什么。

如果有人能解释一下,我将不胜感激。

假设它是合法的,有没有什么方法可以用函子做类似的事情?

4

3 回答 3

2

我假设您打算使用funcfor 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;
}
于 2013-07-16T19:33:15.310 回答
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);

编译器看到这是在 object 上调用std::cout的 type basic_ostream<char,char_traits<char>>,并且唯一与调用匹配的特化operator<<是 wherecharT == chartraits == char_traits<char>and 选择正确的特化。

于 2013-07-16T19:40:11.867 回答
0

在 Visual Studio 2010 上,解决方案既简单又微妙。您只需<int>在行中的 printname 之后添加applyfunc(a,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;
}
于 2014-09-12T00:28:29.927 回答