0

I'm trying to instantiate a template class using an instantiation of the same template class as the type. Previous answers using an instantiation of a different template class suggest that this code should work:

#include <stdio.h>
#include <typeinfo>

template <class T> class pair {
private:
    T first;
    T second;
public:
    pair(T x, T y) {
        first = x;
        second = y;
    }

    void printit() {
        if (typeid(int) == typeid(T)) {
            printf("pair(%i,%i)\n", first, second);
        } else {
            printf("type not supported yet\n");
        }
    }
};
int main(int argc, char ** argv) {
    printf("simplertest\n");
    int one = 1;
    int two = 2;
    pair<int> pi(one,two);
    pair<pair<int> > pp(pi, pi); // should make pair whose members are pairs
}

but I get an error from g++

> g++ simplertest.cpp
simplertest.cpp: In instantiation of ‘pair<T>::pair(T, T) [with T = pair<int>]’:
simplertest.cpp:27:31:   required from here
simplertest.cpp:9:20: error: no matching function for call to ‘pair<int>::pair()’
     pair(T x, T y) {
                    ^
simplertest.cpp:9:5: note: candidate: pair<T>::pair(T, T) [with T = int]
     pair(T x, T y) {
     ^~~~
simplertest.cpp:9:5: note:   candidate expects 2 arguments, 0 provided
simplertest.cpp:4:26: note: candidate: constexpr pair<int>::pair(const pair<int>&)
 template <class T> class pair {
                          ^~~~
simplertest.cpp:4:26: note:   candidate expects 1 argument, 0 provided
simplertest.cpp:4:26: note: candidate: constexpr pair<int>::pair(pair<int>&&)
simplertest.cpp:4:26: note:   candidate expects 1 argument, 0 provided
simplertest.cpp:9:20: error: no matching function for call to ‘pair<int>::pair()’
     pair(T x, T y) {
                    ^
simplertest.cpp:9:5: note: candidate: pair<T>::pair(T, T) [with T = int]
     pair(T x, T y) {
     ^~~~
simplertest.cpp:9:5: note:   candidate expects 2 arguments, 0 provided
simplertest.cpp:4:26: note: candidate: constexpr pair<int>::pair(const pair<int>&)
 template <class T> class pair {
                          ^~~~
simplertest.cpp:4:26: note:   candidate expects 1 argument, 0 provided
simplertest.cpp:4:26: note: candidate: constexpr pair<int>::pair(pair<int>&&)
simplertest.cpp:4:26: note:   candidate expects 1 argument, 0 provided
> g++ --version
g++ (SUSE Linux) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

What am I doing wrong here?

Richard Parkins
  • 347
  • 2
  • 13

1 Answers1

1

The issue is that you are using assignment over initialization in your pair constructor.

pair(T x, T y) 
{ //here
    first = x;
    second = y;
}

By the time the opening bracket (marked with comment) is reached, all of the data members in class must be initialized.
int has default initializer, so there is no problem with pair<int> - first and second are default initialized and then overridden in your constructor body.
However, pair does not provide a default constructor. When you try pair<pair<int>> (so T is of type pair<int>) first and second cannot be initialized, thus the error.

The solution is to use member initilization list:

pair(T x, T y) : first{x}, second{y}
{
}
Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52
  • "all of the data " not really "all" of them must be initialized – 463035818_is_not_an_ai Jan 08 '21 at 12:36
  • @largest_prime_is_463035818 Can you elaborate? Which data members can be not initialized before constructor body? – Yksisarvinen Jan 08 '21 at 12:38
  • i refer to "all of the data members in class must be initialized". Could be more clear. Specifically there was no problem with assignment in the constructor in OPs `pair` to the `int` member ( `int` has no default constructor too ;) – 463035818_is_not_an_ai Jan 08 '21 at 12:40
  • largest_prime_is_463035818, I think `int` *does* have a default constructor, whatever random value is in the memory cell allocated. Perhaps Yksisarvinen should have said "must be constructed" rather than "must be initialized", or maybe "all data members which are classes or contain classes". A class member which is a `struct`, for example, does not need to be initialized. – Richard Parkins Jan 09 '21 at 18:38