2012-01-22 18 views
0

私は主コンパイルを可能にするために次のネストしたクラスに型キャスト演算子を追加する方法を理解しようとしていますが、何が必要なのか分からないのです。問題。最後の割り当てでは、型キャストを使用して機能させることに注意してください。私は "add"クラスの型キャスト演算子を定義する必要があると思われますが、どうですか?ネストされたテンプレート型キャスト

長いリストで申し訳ありませんが、これは私がそれを作る方法を知っているほど簡単です。

#include <iostream> 
using namespace std; 

template <char I> struct index { }; 

template <char I, char J> struct marker; 

// simple class with just a 2 element int array 
struct A { 
    A() { } 
    A(int i, int j) { a[0] = i; a[1] = j; } 
    A(const A& x) { a[0] = x(0); a[1] = x(1); } 

    template<char I, char J> 
    marker<I,J> operator()(const index<I>&, const index<J>&) { 
    return marker<I,J>(*this); 
    } 

    friend std::ostream& operator<<(std::ostream& os, const A& _A) { 
    return os << '{' << _A.a[0] << ',' << _A.a[1] << '}'; 
    } 

    int& operator()(int i) { return a[i]; } 
    const int& operator()(int i) const { return a[i]; } 

private: 
    int a[2]; 
}; 

template <char I, char J> 
struct marker { 
    const int DI; 
    const int DJ; 

    marker(A& a) : _A(a), DI(1), DJ(0) { } 
    marker(A& a, const int i, const int j) : _A(a), DI(i), DJ(j) { } 
    marker(const marker& m) : _A(m._A), DI(m.DI), DJ(m.DJ) { } 

    // cast I,J => J,I 
    operator marker<J,I>() const { 
    return marker<J,I>(_A, DJ, DI); 
    } 

    marker& operator=(const marker& m) { 
    _A(0) = m(0); 
    _A(1) = m(1); 
    return *this; 
    } 

    // returns the i'th or (1-i)'th element of _A 
    int operator()(int i) const { 
    return _A(i*DI + (1-i)*DJ); 
    } 

    template<class LHS, class RHS> 
    struct add { 
    const LHS& lhs; 
    const RHS& rhs; 

    add(const LHS& l, const RHS& r) : lhs(l), rhs(r) { } 

    int operator()(int i) const { 
     return lhs(i) + rhs(i); 
    } 

    add< add,marker > operator+(const marker& b) { 
     return add< add,marker >(*this, b); 
    } 
    }; 

    add< marker,marker > operator+(const marker& b) const { 
    return add< marker,marker >(*this,b); 
    } 

    template<class LHS> 
    void operator=(const add<LHS,marker>& expr) { 
    _A(0) = expr(0); 
    _A(1) = expr(1); 
    } 

private: 
    A& _A; 
}; 


int main() { 
    index<'i'> i; 
    index<'j'> j; 
    A a(1,2), b; 

    b(i,j) = a(j,i); 
    cout << b << endl; // "{2,1}" 

    b(i,j) = a(i,j) + a(j,i); 
    cout << b << endl; // "{3,3}" 

    b(i,j) = a(j,i) + a(i,j); // fails to compile 
    cout << b << endl; // should be "3,3" 

    b(i,j) = (marker<'i','j'>)a(j,i) + a(i,j); // works fine 
    cout << b << endl; // "{3,3}" 

    return 0; 
} 
+2

これはおそらくあなたの問題の原因ではありませんが、アンダースコアと大文字( '_A'など)で始まる識別子は[任意のスコープで予約されています](http://stackoverflow.com/a/228797/185171) ) –

+0

ありがとう。それを知らなかった。この場合でもコンパイラからの苦情はありません。 – gogators

答えて

0

[解雇] OK、考え出しました。私がしなければならなかったすべては、クラスのマーカーに以下のメンバーを追加しました:

template <class LHS> 
    void operator=(const typename marker<J,I>::template add< LHS, marker<J,I> >& expr) { 
    myA(0) = expr(1); 
    myA(1) = expr(0); 
    } 

パラメータ仕様の構文私をめちゃくちゃにされたものです。 servnは私に手がかりを与え、いくつかの試行錯誤は正しい構文を得ました。

1

打ち鳴らすには、次のエラーを与える:

/tmp/webcompile/_13759_1.cc:97:10: error: no viable overloaded '=' 
    b(i,j) = a(j,i) + a(i,j); // fails to compile 
    ~~~~~~^~~~~~~~~~~~~~~~ 
/tmp/webcompile/_13759_1.cc:44:11: note: candidate function not viable: no known conversion from 'add<marker<'j', 'i'>, marker<'j', 'i'> >' to 'const marker<'i', 'j'>' for 1st argument; 
    marker& operator=(const marker& m) { 
     ^
/tmp/webcompile/_13759_1.cc:76:8: note: candidate template ignored: failed template argument deduction 
    void operator=(const add<LHS,marker>& expr) { 
    ^

エラーがちょうどコンパイラは、問題の割り当てを実行する方法を見つけることができませんを意味します。コンパイラはそれを試みた2つのをリストします。最初は明らかに一致しません。 2番目の場合、failed template argument deductionは、任意のタイプのLHSに対して、引数をconst add<LHS,marker>&に変換する方法をコンパイラーが判別できないことを意味します。おそらくあなたは次のことが欲しいのですか?

template<class LHS, class RHS> 
void operator=(const add<LHS,RHS>& expr) 

EDIT:あなたが明示的にオペレーターを呼び出す=とテンプレートパラメータを強制する場合は 、問題がより明らかになった:

/tmp/webcompile/_28787_0.cc:95:10: error: no matching member function for call to 'operator=' 
    b(i,j).operator=<marker<'j', 'i'>, marker<'j', 'i'> >(a(j,i) + a(i,j)); // fails to compile 
    ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/tmp/webcompile/_28787_0.cc:76:6: note: candidate function [with LHS = marker<'j', 'i'>, RHS = marker<'j', 'i'>] not viable: no known conversion from 'add<marker<'j', 'i'>, marker<'j', 'i'> >' (aka 'marker<'j', 'i'>::add<marker<'j', 'i'>, marker<'j', 'i'> >') to 'add<marker<'j', 'i'>, marker<'j', 'i'> >' (aka 'marker<'i', 'j'>::add<marker<'j', 'i'>, marker<'j', 'i'> >') for 1st argument; 
void operator=(add<LHS,RHS>); 
    ^

は具体的には、パラメータがmarker<'i', 'j'>::addで、引数がありmarker<'j', 'i'>::add

+0

それはそれのようなものだったと考えました。あなたの提案は、より一般的ですが、同様のエラーが発生します。 – gogators

+0

また、エラーを返す行で 'b(i、j)'を 'b(j、i)'に変更すると、パラメータは 'marker <'j', 'i'> :: add'になり、コードがコンパイルされます。しかし、私はその解決策が何であるか疑問に思います。 –

関連する問題