3

私はC++11の機能に比較的慣れていません。自動機能と、それがどのようにファンクターをタイプ推論するかについて質問があります。次のコードスニペットについて考えてみます。

bool test1(double a, double b) {
   return (a<b);
}

   bool test2(double a, double b) {
       return (a>b);
   }

   struct Test1 {
       bool operator()(double a, double b) {
          return (a<b);
       }
   };

   struct Test2 {
       bool operator()(double a, double b){
          return (a>b);
       }
   };

   int main() {
       const bool ascending = false; 
      auto comparator =  ascending? test1:test2; // works fine
      auto comparator2 = ascending? Test1():Test2(); // compiler error: imcompatible types
      std::function<bool(double, double)> comparator3 = ascending? Test1():Test2(); // compiler error: imcompatible types;

   }

auto(およびstd :: function)は関数に対しては正常に機能しますが、関数オブジェクトに対しては失敗します(型推定)。どうしてこれなの?ここでタイプ控除の基本的なものが欠けています。

(私はVisual Studio 2012を使用しています)

4

3 に答える 3

10

条件付き?)演算子に関するC++11標準の5.16/3項によると:

[...] 2番目と3番目のオペランドのタイプが異なり、(おそらくcv修飾された)クラスタイプがある場合、または両方が同じ値カテゴリのglvalueであり、cv修飾を除いて同じタイプである場合、試行が行われます。これらの各オペランドを他のタイプに変換します。[...] 両方を変換できる場合、または一方を変換できるが変換があいまいな場合、プログラムの形式が正しくありません。[...]

あなたの場合、どちらTest1Test2他のタイプに変換することはできません。これが、コンパイラが「互換性のない型」について不平を言っている理由です。

Nptice、これが当てはまらない場合、comparator2およびのタイプは、の値に基づいて実行時comparator3に決定されます。ただし、C ++は静的に型付けされた言語であるため、すべてのオブジェクトの型はコンパイル時に決定する必要がありますascending

コンパレータの実行時選択を実行し、結果を1つの変数に保持する必要がある場合は、最初に両方のオブジェクトを、両方をカプセル化できる同じタイプのファンクタに割り当ててから、選択を実行することを検討してください

    std::function<bool(double, double)> c1 = Test1();
    std::function<bool(double, double)> c2 = Test2();
    auto c = (ascending) ? c1 : c2;
于 2013-03-26T21:10:05.147 に答える
3

問題は、条件演算子の2つのオプションが?:単一の共通型に変換可能でなければならないことです。この場合、Test1Test2は関係がなく、そのような演算子を使用することはできません。

ただし、これは合法です。

 int main() {
      const bool ascending = false; 
      std::function<bool(double, double)> t1 = Test1();
      std::function<bool(double, double)> t2 = Test2();
      auto comparator4 = ascending? t1: t2;
   }
于 2013-03-26T21:08:35.793 に答える
3

test1test2どちらもタイプでbool(double, double)あるため、条件式のタイプは、どのブランチを使用しても同じです。のタイプTest1()Test1、のタイプはTest2()ですTest2。したがって、式には共通の型はありません。これらのタイプは両方とも、そのクラスのコンストラクターテンプレートを使用してオブジェクトを構築するために使用できstd::function<bool(double, double)>ますが、この種のキャストは式に対して自動的に実行されません。手動でキャストする必要があります。

auto comparator3 = ascending ? std::function<bool(double, double)>(Test1())
                             : std::function<bool(double, double)>(Test2());
于 2013-03-26T21:08:50.060 に答える