приведение типа вложенного шаблона - PullRequest
0 голосов
/ 23 января 2012

Я пытаюсь выяснить, как добавить оператор typecast к следующему вложенному классу, чтобы позволить main скомпилировать, но я не могу понять, что нужно. Следующее после последнего назначения в main вызывает проблему. Обратите внимание, что самое последнее назначение использует приведение типов, чтобы оно работало. Я подозреваю, что мне нужно определить либо оператор typecast для класса 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 ]

1 голос
/ 23 января 2012

clang выдает следующую ошибку:

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

Ошибка просто означает, что компилятор не может найти способ выполнить соответствующее задание. Затем компилятор перечисляет два operator=, которые он пробовал. Первое явно не соответствует. Во-вторых, failed template argument deduction просто означает, что компилятор не может понять, как преобразовать аргумент в const add<LHS,marker>& для любого типа LHS. Возможно, вы хотите следующее?

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

EDIT: Если вы явно вызовете operator = и принудительно задаете параметры шаблона, проблема становится более очевидной:

/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 голосов
/ 23 января 2012

[решено] ОК, разобрался. Все, что мне нужно было сделать, это добавить следующего члена в маркер класса:

  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 дал мне подсказку, и некоторые пробные версии и ошибки получили правильный синтаксис.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...