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 を手元に持っていません) が拒否したという事実は、コンパイラのバグのように見えます。

Re: ファンクタに似たもの - これでうまくいくかどうかを確認してください:

#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関数は 型の関数を取るため、 meanにvoid (std::string const&)解決されますが、コンパイラの初期化の場合、特殊化に解決されます。ff<std::string>fnf<double>

これは言語の非常に一般的に使用される機能であることに注意してください。

std::cout << std::endl;

名前std::endlはテンプレートを参照します。

template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);

コンパイラは、 this がstd::couttype の object で呼び出されていること、およびbasic_ostream<char,char_traits<char>>への呼び出しに一致する唯一の特殊化operator<<が wherecharT == charおよびtraits == char_traits<char>and であり、正しい特殊化を選択していることを確認します。

于 2013-07-16T19:40:11.867 に答える