13

以下の関数について考えてみます。この関数barのパラメーターには、オーバーロードされた呼び出しから初期化されたデフォルト値がありますfoo

#include <iostream>

int foo(int x)
{
  std::cout << "foo(int)" << std::endl;
  return 0;
}

template<typename T>
void bar(T a, int x = foo(T(0))) {}

double foo(double x)
{
  std::cout << "foo(double)" << std::endl;
  return 0;
}

int main()
{
  bar<int>(1);
  bar<double>(1);
  return 0;
}

このプログラムが出力することを期待しています

foo(int)
foo(double)

のインスタンス化fooで表示されるの2つのオーバーロードに対応します。bar

代わりに、でコンパイルするとg++-4.6、出力は次のようになります。

$ g++-4.6 -std=c++0x test.cpp; ./a.out 
foo(int)
foo(int)

デフォルトのパラメーター値を実装するときに、オーバーロードのセットは通常のオーバーロード解決とは異なりますか?このケースはISOC++標準で説明されていますか?

4

3 に答える 3

6

このプログラムは、考慮される一連の関数が通常の過負荷解決規則に従うことを示唆しています。

#include <iostream>

struct type1 {};
struct type2 {};

int foo(type1 x)
{
  std::cout << "foo(type1)" << std::endl;
  return 0;
}

template<typename T>
void bar(int x = foo(T())) {}

int foo(type2 x)
{
  std::cout << "foo(type2)" << std::endl;
  return 0;
}

int main()
{
  bar<type1>();
  bar<type2>();
  return 0;
}

でコンパイルするとg++-4.6、このプログラムは次のように出力します。

$ g++ test_2.cpp ; ./a.out 
foo(type1)
foo(type2)

つまり、がインスタンス化fooされると、ADLを介して解決されます。bar

OPからのコードの動作は、ADLがやなどのプリミティブに適用されないように思われるintため、考慮されるオーバーロードは、の呼び出しのdouble前に宣言されたものだけです。foo奇妙なMSVCの動作は非標準のようです。

于 2012-11-21T00:57:05.097 に答える
3

これは、標準がこれについて述べていることです。まず、8.3.6 [dcl.fct.default]の段落5:

...デフォルトの引数の名前はバインドされ、デフォルトの引数が表示されるポイントでセマンティック制約がチェックされます。関数テンプレートおよびクラステンプレートのメンバー関数のデフォルト引数の名前ルックアップとセマンティック制約のチェックは、14.7.1で説明されているように実行されます。..。

さらに14.7.1[temp.inst]段落12:

デフォルトの引数を使用する必要がある方法で関数テンプレートfが呼び出された場合、依存する名前が検索され、セマンティクスの制約がチェックされ、デフォルトの引数で使用されるテンプレートのインスタンス化がデフォルトの引数のように行われます。は、その時点で使用されていた関数テンプレートfと同じスコープ、同じテンプレートパラメータ、および同じアクセスを持つ関数テンプレートスペシャライゼーションで使用されるイニシャライザでした。この分析は、デフォルトの引数のインスタンス化と呼ばれます。インスタンス化されたデフォルトの引数は、fの引数として使用されます。

これが正確に何を言っているのかよくわかりません。私はこのテキストで両方の解釈を見ることができます。重要な場合は、EDGはgccとclangに同意すると思います。

于 2012-11-21T00:45:23.807 に答える
1

テンプレートの後にオーバーロードされた関数"foo(double)"を宣言して定義したためか、その存在について何も知りません。->構造化プログラミング。私は提案します:

#include <iostream>

int foo(int x)
{
std::cout << "foo(int)" << std::endl;
  return 0;
}

double foo(double x)
{
std::cout << "foo(double)" << std::endl;
return 0;
}

template<typename T>
void bar(T a, int x = foo(T(0))) {}



int main()
{
bar<int>(1);
bar<double>(1);
return 0; 
}
于 2012-11-21T00:48:40.217 に答える