2012-01-22 2 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

[해독] 좋아, 알아 냈어. 클래스 마커에 다음 멤버를 추가하면됩니다.

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) { 
    ^

오류는 컴파일러가 문제의 할당을 수행 할 수있는 방법을 찾을 수 없음을 의미합니다. 그런 다음 컴파일러에서 시도한 두 개의 을 나열합니다. 첫 번째는 분명히 일치하지 않습니다. 두 번째로는 failed template argument deduction은 컴파일러가 LHS 유형의 인수를 const add<LHS,marker>&으로 변환하는 방법을 파악할 수 없다는 것을 의미합니다. 아마 당신은 다음을 원합니까?

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

는 편집 :

/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)'로 변경하면 매개 변수는 마커 <'j', 'i'> :: add'가되어 코드가 컴파일됩니다. 그러나 그 해결책이 무엇인지 궁금합니다. –