Аргумент шаблона и собственный аргумент шаблона содержат типы с одинаковыми именами; как я могу ссылаться на второй в сигнатуре функции?

Рассмотрим этот код:

template<typename T>
struct Foo
{
    typedef T t_type;
};

template<typename T>
struct Bar
{
    typedef T t_type; 
};

template<typename U>
auto f() -> typename U::t_type::t_type
{
    return typename U::t_type::t_type();
}

int main(int, char**)
{
    typedef Foo<Bar<int>> Baz;
    f<Baz>();
}

Он не компилируется под VS2012:

недопустимые явные аргументы шаблона для 'U::t_type::{ctor} f(void)'

Похоже, компилятор заключает, что второе t_type в typename U::t_type::t_type именует конструктор, а не вложенный тип с одинаковым именем. Что я могу сделать, чтобы помочь прояснить ситуацию?

2 ответа

Решение

Сначала вам не хватает typename ключевое слово

template<typename U>
auto f() -> typename U::t_type::t_type
{
    return typename U::t_type::t_type();
}

и главное должно иметь аргументы (int,char**),

Это сказал..

об этом уже было сообщено и, по-видимому, исправлено ([будет / было] отправлено в неуказанной "будущей версии"). MSVC 2013 обновление 4 также влияет.

Предлагаемый обходной путь:

template<typename T>
struct Foo
{
    typedef T t_type;
};

template<typename T>
struct Bar
{
    typedef T t_type;
};

template<typename U>
auto f() -> typename U::t_type::template t_type
                                ^^^^^^^^
{
    return typename U::t_type::t_type();
}

int main(int, char**)
{
    typedef Foo<Bar<int>> Baz;
    f<Baz>();
}

хотя, если вы используете приведенный выше код, все будет так, как показано на следующем рисунке:

введите описание изображения здесь

Я не думаю, что это поддерживается в 2012 году, но:

template<class T>
using t_type=typename T::t_type;

template<typename U>
t_type<t_type<U>> f() {
  return {};
}

В 2012 году мы могли бы попробовать это:

template<class T, size_t recurse>
struct r_type:
  r_type<typename T::t_type, recurse-1>
{};
template<class T>
struct r_type<T, 0> {
  typedef typename T::t_type t_type;
};

...

template<typename U>
auto f() -> typename r_type<U,1>::t_type {
  return {};
}

где r_type расшифровывается как "рекурсивный тип".

Другие вопросы по тегам