2017-01-13 1 views
5
#include <iostream> 
using namespace std; 

class A 
{ 
    public: 
    A() : x(0) {} 
    // notice: not identical to const version but does update 
    void FA() {std::cout << "A" << std::endl; x++;} 
    void FA() const {std::cout << "const A" << std::endl;} 
    private: 
    int x; 
}; 

class B 
{ 
    public: 
    B() : x(0) {} 
    // notice: not identical to const version but does update 
    void FB() {std::cout << "B" << std::endl; x++;} 
    void FB() const {std::cout << "const B" << std::endl;} 
    private: 
    int x; 
}; 

class C 
{ 
    public: 
    void FC() 
    { 
     bool condition = true; // should be set to a real condition 

     if(condition) 
     { 
      a.FA(); 
     } 
     b.FB(); 
    } 

    void FC() const 
    { 
     bool condition = true; // should be set to a real condition 

     if(condition) 
     { 
      a.FA(); 
     } 
     b.FB(); 
    } 

    private: 
    A a; 
    B b; 
}; 

int main() { 
    C c; 
    c.FC(); 

    const C cc; 
    cc.FC(); 

    return 0; 
} 

まず、長いタイトルを残して申し訳ありません。 関数内のクラスCでコードの重複を避ける方法FCFC constこのからconstのキャスティングトリックを使用することはできず、非const FCの本体は実際には更新を行う関数を呼び出すため、const FCバージョンを非const FCバージョンから呼び出すことはできません定数。意味的に同一でない構文的に同一のconst関数と非const関数の間のコードの重複を回避する方法

+0

:この例では、それは後に修正し、進化へのクラスCがより容易になるだろう彼らは両方を呼び出すことができます。 –

+1

「すべての」機能に同じ名前が選択されているため、見かけ上のコードの重複があります。 'Print()const'と' FA'の代わりに 'PrintAndUpdate()'があれば、その複製は魔法のように消えてしまいます。 –

+1

これは質問には答えませんが、余分なものが必要な場合を除き、 'std :: endl'を使用しないでください。 '' \ n ''は行を終わらせます。 –

答えて

7

テンプレートメンバ関数を実際の作業にします。言い換えれば、これを試してみてください:

class C 
{ 
public: 
    void FC() 
    { 
     FC_Impl(*this); 
    } 

    void FC() const 
    { 
     FC_Impl(*this); 
    } 

private: 
    template <typename Self> 
    static void FC_Impl(Self & self) 
    { 
     bool condition = true; // should be set to a real condition 

     if(condition) 
     { 
      self.a.FA(); 
     } 
     self.b.FB(); 
    } 

    A a; 
    B b; 
}; 
+0

「メンバー関数に自由機能を常に好んでいる理由」+1 –

+2

@RichardHodges静的メンバー関数はメンバ関数 –

+0

@ M.Mです。この場合、私は友人の機能を考えていました。もっと表現力豊かなジェネリックプログラミングを可能にするので、私はまだメンバー関数に自由な関数を好むと思う。 –

0

偉大な答えはRalphです。同じ名前のフリー関数を提供することに言及する価値はあると思いますが、異なる引数型では、自由な関数がアダプターとして機能する一方で、高いレベルで意図を表現することができます。私たちは、ADLが適切な関数のオーバーロード(または特殊化)を見つけることを許可します。

このように、論理を表現するためにメンバー関数の名前を知る必要はありません。機能が異なっているので、私は彼らに別の名前を与えることをお勧めしますが、単一の関数に共通のコードを取得しようと思います

#include <iostream> 
#include <utility> 
using namespace std; 

// general case 
template<class T> 
    decltype(auto) apply_F(T&& t) 
{ 
    return t.F(); 
} 

// call apply_F with either an X or a Y and return the result)can be void) 
template<class X, class Y> 
    auto conditionally_apply_F(bool condition, X&& x, Y&& y) 
    -> std::common_type_t<decltype(apply_F(x)), decltype(apply_F(y))> 
{ 
    if (condition) { 
    return apply_F(x); 
    } 
    else { 
    return apply_F(y); 
    } 
} 

// provides F member function - no need for specific adapter 
class A 
{ 
    public: 
    A() : x(0) {} 
    // notice: not identical to const version but does update 
    void F() {std::cout << "A" << std::endl; x++;} 
    void F() const {std::cout << "const A" << std::endl;} 
    private: 
    int x; 
}; 


// has differing names implementing the concept of F - so we'll need an adapter 
class B 
{ 
    public: 
    B() : x(0) {} 
    // notice: not identical to const version but does update 
    void F_mutable() {std::cout << "B" << std::endl; x++;} 
    void F_const() const {std::cout << "const B" << std::endl;} 
    private: 
    int x; 
}; 

// adapter overloads 
decltype(auto) apply_F(B const& t) 
{ 
    return t.F_const(); 
} 

decltype(auto) apply_F(B& t) 
{ 
    return t.F_mutable(); 
} 

// class C current expressed in terms of A and B, but no longer tied to these types  
class C 
{ 
    public: 
    void FC() 
    { 
     bool condition = true; // should be set to a real condition 
     conditionally_apply_F(condition, a, b); 
    } 

    void FC() const 
    { 
     bool condition = true; // should be set to a real condition 
     conditionally_apply_F(condition, a, b); 
    } 

    private: 
    A a; 
    B b; 
}; 

int main() { 
    C c; 
    c.FC(); 

    const C cc; 
    cc.FC(); 

    return 0; 
} 
関連する問題