Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default constructor defined with default arguments outside the class definition, why does this work? and what happens with templates involved?

I am aware this is bad form and that default-values should be specified in the declaration, but if you would please indulge me for a moment.. why does this compile? and what is happening exactly?

#include <iostream>
using namespace std;

class test
{
public:
    test(int n);
};

test::test(int n = 666)
{
    cout << n;
}

int main()
{
    test t;

    cin.sync();
    cin.ignore();

    return 0;
}

Output: 666

.. how do templates affect the same piece of code?

template <class T>
class test
{
public:
    test(int n);
};

template <class T>
test<T>::test(int n = 666)
{
    cout << n;
}

int main()
{
    test<int> t;

    cin.sync();
    cin.ignore();

    return 0;
}

Error: no appropriate default constructor available

Thank you for your time!

like image 608
whysoconfused Avatar asked Jul 24 '11 07:07

whysoconfused


2 Answers

It looks like the C++ specification specifically allows the first case and disallows the second!

Quote from the C++ spec (§8.3.6/4):

For non-template functions, default arguments can be added in later declarations of a function in the same scope.

So it looks like for non-template functions, you can indeed introduce the default arguments later on. No idea why this doesn't work for templates, though!

like image 139
templatetypedef Avatar answered Nov 17 '22 08:11

templatetypedef


The first case is allowed by standard; I remember that was asked by @Johannes and answered by @Nawaz. (Edit: Here is the related question).

Reason for not allowing the template version is because template functions are called only when instantiated explicitly. In your case, compiler looks at the declaration as,

test<int> t;

-->Edit: It might differ from compiler to compiler. In gcc it works fine.<--

Why it may not work in some compiler might be Since you are not explicitly instantiating as t(N), compiler will not be able to resolve test<T>::test(int n = 666). Thus it looks for default constructor with no argument, which is not found; thus resulting in error.

like image 36
iammilind Avatar answered Nov 17 '22 09:11

iammilind