Проблема с функциями, принимающими внутренние классы шаблонных классов - PullRequest
4 голосов
/ 24 августа 2011

У меня проблема с внутренними классами в шаблонах классов.У меня есть шаблон класса (скажем: Matrix<T>) и подкласс (скажем: Matrix<T>::Row).Теперь я хочу написать функцию, которая работает с экземплярами подкласса (скажем: negate(Matrix<T>::Row &)).Я пытался объявить функцию с помощью template<class T> negate(typename Matrix<T>::Row &), но когда я пытаюсь ее использовать, компилятор сообщает мне, что не может найти совпадение.

Вот абстрактный пример:

template<class T>
class A
{
public:
    class B
    {
    };
};

template<class T>
void x(typename A<T>::B &)
{
}

int main()
{
    A<int>::B b;
    x(b); // doesn't work: Error: Could not find a match
          // for x<T>(A<int>::B) needed in main().
    x<int>(b); // works fine
}

Почему компилятору не удается найти x в первом случае?Есть ли способ изменить это, чтобы он работал (без явного указания типа int)?

(у меня также есть подобные проблемы, когда x имеет форму template<class T, class S> void x(typename A<T>::B &, const S &);, поэтому я действительно хотел бы, чтобы меня не принуждали явно указывать имена всех типов при выполнении вызова.)

Я пробовал это с g ++ 4.4.3, g ++ 4.5.2 и Sun Studio 5.9, все дают одинаковый результат.Заранее большое спасибо за все полезное!

Ответы [ 3 ]

3 голосов
/ 24 августа 2011

Как компилятор должен быть в состоянии вывести это?Представьте себе следующую настройку:

struct A { typedef int T; };
struct B { typedef int T; };

template <typename S> void foo(typename S::T);

Теперь, когда вы говорите int x; foo(x);, невозможно однозначно сопоставить это.

Дело в том, что вы не выводите параметр шаблона из заданногошаблон класса, а скорее просто произвольный, отдельно стоящий тип.Тот факт, что этот тип был определен внутри другого класса, не имеет к этому отношения.

2 голосов
/ 24 августа 2011

Это не выводимый контекст. Вот почему аргумент шаблона не может быть выведен компилятором.

Представьте себе, вы могли бы специализировать A следующим образом:

template <>
struct A<SomeType>
{
    typedef std::map <double, double> B;
};

Теперь эта специализация имеет вложенный тип с именем B, который является typedef, равным std::map<double,double>.

Так как бы компилятор мог определить тип SomeType, учитывая, что A<SomeType>::B равно std::map<double, double>?

И на самом деле таких специализаций может быть много:

template <>
struct A<SomeOtherType>
{
    typedef std::map <double, double> B;
};

Даже эта специализация имеет B как вложенный тип.

Теперь, если я скажу A<T>::B - это std::map<double,double>, тогда вы можете сказать, что такое T? Это SomeType? или SomeOtherType?

1 голос
/ 24 августа 2011

Потребуется вывести тип T для вызова функции шаблона x, а вычитание аргумента шаблона допускается только в определенных обстоятельствах:

http://publib.boulder.ibm.com/infocenter/compbgpl/v9v111/index.jsp?topic=/com.ibm.xlcpp9.bg.doc/language_ref/template_argument_deduction.htm

A<T>::B

не похоже на один из них: /

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