2017-08-11 11 views
3

私はC++に関するいくつかの新しい概念を学んでおり、それらと遊んでいます。 私は実際にどのように動作するかについて私を混乱させるコードを書きました。クラスとヘルパー関数との混乱でパラメータ化されたクラス

#include <iostream> 

class aid { 
public: 
    using aid_t = std::string; 
    void setaid(const std::string& s) { 
     aid_ = s; 
    } 
    const aid_t& getaid() const { 
     return aid_; 
    } 
private: 
    aid_t aid_; 
}; 

class c { 
public: 
    using c_t = std::string; 
    void setc(const aid::aid_t& aid_val) { 
     if (aid_val.size() < 4) 
      c_ = "yeah"; 
     else 
      c_ = aid_val + aid_val; 
    } 
    const c_t& getc() { 
     return c_; 
    } 
private: 
    c_t c_; 
}; 

template<typename ...Columns> 
class table : public Columns... { 
}; 

template <typename... Columns> 
void f(table<Columns...>& t) { 
    t.setaid("second"); 
    std::cout << t.getaid() << "\n"; 
} 

void f2(table<aid>& t) { 
    t.setaid("third"); 
    std::cout << t.getaid() << "\n"; 
} 

int main() { 
    table<aid, c> tb; 
    tb.setaid("first"); 
    std::cout << tb.getaid() << " " << "\n"; 
    // f<c>(tb); // (1) doesnt compile, that seem obvious 
    f<aid>(tb); // (2) works? 
    f(tb); // (3) works too -- template parameter deduction 
    // f2(tb); // (4) doesnt work? worked with (2)... 
} 

ここのアイデアは簡単ですが、私はいくつかの列のテーブルを持っています。そして、いくつかの列のセットだけを必要とするいくつかの関数を作成したいと思います。渡された引数に余分な列があるかどうかは気にしません。

私の混乱は、主にコードのポイント(2)と(4)です...私の直感は、それが同じでなければならない理由は何か、そして(2)コンパイルと(4)私が紛失している重要なトピックはありますか? この特定の機能を実現する方法はありますか? Cheers

答えて

3

コンパイラは残りのテンプレートパラメータパックを引き続き計算し、関数パラメータとしてtable<aid, c> &を取得します。これは(4)(table<aid> &)とは異なります。

[temp.arg.explicit]/3:演繹(14.8.2)またはデフォルトテンプレート引数から を得ることができ

末尾のテンプレート引数は 明示的なテンプレート引数のリストから省略することができます。それ以外の場合には推定されない末尾のテンプレートパラメータパック (14.5.3)は、テンプレート引数の空のシーケンスであると推定されます( )。すべてのテンプレート引数を推定できる場合は、 を省略することができます。この場合、空のテンプレート引数 リスト<>自体も省略することができます。控除が で、控除が行われないコンテキストでは、 テンプレート引数リストが指定され、デフォルトの テンプレート引数とともに単一の関数テンプレート 特殊化が識別される場合、 idは関数 テンプレートの特殊化の左辺値です。

関連する問題