В теле функции-члена класса шаблона вне определения класса, когда требуются параметры шаблона?

Этот код компилируется (Visual Studio 2013). Обратите внимание, что я передаю Set, а не Set<T>, в качестве параметра operator= в теле функции, которое находится за пределами определения класса. Но я не могу вернуть Set или сделать его членом Set; он должен возвращать Set<T> и быть членом Set<T>.

Где допустимо не указывать параметры шаблона? Внутри определения класса, а где еще?

Это изменение стандарта? Я пытаюсь сохранить совместимость со всеми существующими версиями, включая 98.

template <typename T>
class Set 
{
public:
    Set() {}         

    const Set& operator=(const Set& rhs); 
    //Shouldn't this have to be 
    //const Set<T>& operator= (const Set<T>& rhs); ?

};

template <typename T>
const Set<T>& Set<T>::operator= (const Set& rhs) //<-- HERE
{
    Set temp;                                    //<-- AND HERE
    /* ... */
    return *this;
}

int main()
{
    Set<int> S, T;
    T = S;
}

person Topological Sort    schedule 15.04.2016    source источник
comment
AFAIK только классы делают это, так как у них есть имя введенного класса   -  person NathanOliver    schedule 15.04.2016
comment
и здесь: template <typename T> auto Set<T>::operator=(const Set&) -> const Set&   -  person Piotr Skotnicki    schedule 15.04.2016
comment
void main недействителен и помешал бы многим (большинству) читателей опробовать ваш код. Я исправил это. Пожалуйста, не публикуйте код с void main, если только вопрос не касается конкретно этого, потому что это вводит в заблуждение читателей-новичков и делает невозможным просто скопировать и вставить ваш код, чтобы попробовать его, если только вы не используете один из немногих компиляторов, которые его принимают. .   -  person Cheers and hth. - Alf    schedule 15.04.2016


Ответы (1)


Имя класса становится доступным в области класса. А в отдельном определении члена после того, как вы передали спецификацию возвращаемого типа C++03 и имя функции, вы попадаете в область действия класса. Таким образом, это нормально в С++ 03:

template< class T >
Set<T> const& Set<T>::operator=( Set const& rhs ) 

И это нормально в С++ 11:

template< class T >
auto Set<T>::operator=( Set const& rhs) -> Set const&

На самом деле это не имеет ничего общего с шаблонами, но связано с доступом к имени, доступному в области класса.

Например, в C++03 вам нужно было бы написать

struct S
{
    struct Inner {};
    Inner foo();
};

S::Inner S::foo() { return Inner(); }

в то время как с С++ 11 и более поздними версиями вы можете написать

struct S
{
    struct Inner {};
    auto foo() -> Inner;
};

auto S::foo() -> Inner { return {}; }

что является одной из веских причин, среди многих других, для принятия синтаксиса завершающего возвращаемого типа в качестве единого синтаксического соглашения.


Это не подходит ни для C, ни для C++, независимо от стандарта того года:

void main() //! NOT VALID.
person Cheers and hth. - Alf    schedule 15.04.2016
comment
Вы знаете, допустимо ли то, что у вас есть, в C++98? - person Topological Sort; 16.04.2016
comment
Код C++03 действителен с компилятором C++98. Единственной новой функцией, представленной в C++03, была инициализация значений. C++03 был всего лишь техническим исправлением C++98, который в то время назывался TC1 (он был первым и единственным). - person Cheers and hth. - Alf; 16.04.2016