2021-07-11

23: Explicitly Instantiate Constructor Template for Visual C++

<The previous article in this series | The table of contents of this series | The next article in this series>

An expression that is meant to explicitly instantiate a class constructor template causes some enigmatic errors for Visual C++, although fine for GCC.

Topics


About: C++
About: Visual C++
About: template

The table of contents of this article


Starting Context



Target Context


  • The reader will know that a type of expressions that are meant to explicitly instantiate class constructor templates is not allowed for Visual C++, and an alternative expression to be used.

Orientation


There are some more articles on Visual C++ peculiarities (an "unable to match function definition to an existing declaration" error, exporting the symbols from a DLL, the 'std::codecvt<char16_t,char,struct _Mbstatet>' unresolved error, the "C2131: expression did not evaluate to a constant" error).


Main Body

Stage Direction
Hypothesizer 7 soliloquies.


1: Meeting a Set of Enigmatic Errors for an Explicit Instantiation of a Class Constructor Template


Hypothesizer 7
This class has a constructor template (the '.cpp' file is not shown here).

'theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassA.hpp'

@C++ Source Code
#ifndef __theBiasPlanet_coreUtilitiesTests_templatesTest1_ClassA_hpp__
	#define __theBiasPlanet_coreUtilitiesTests_templatesTest1_ClassA_hpp__
	
	namespace theBiasPlanet {
		namespace coreUtilitiesTests {
			namespace templatesTest1 {
				template <typename T> class ClassA {
					public:
					    ClassA ();
					    template <typename U> ClassA (U a_argument0);
				};
			}
		}
	} 
#endif

This is meant to explicitly instantiate the class constructor template.

'theBiasPlanet/coreUtilitiesTests/templatesTest1/TemplatesInstantiator.cpp'

@C++ Source Code
#include "theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassA.tpp"

using namespace ::theBiasPlanet::coreUtilitiesTests::templatesTest1;

template class ClassA <int>;
template ClassA <int>::ClassA <double> (double a_argument0); // This causes a series of errors for Visual C++

GCC compiles it fine.

Visual C++ rebukes it, with these errors: "error C2039: 'theBiasPlanet::coreUtilitiesTests::templatesTest1::ClassA<double>': is not a member of 'theBiasPlanet::coreUtilitiesTests::templatesTest1::ClassA<int>'" and "error C2062: type 'double' unexpected".

Huh? What do you mean?


2: A Solution and Reasoning


Hypothesizer 7
It seems that Visual C++ does not allow any type parameter value of any class constructor template to be explicitly specified.

In fact, Visual C++ accepts this.

@C++ Source Code
template ClassA <int>::ClassA (double a_argument0);

The type parameter values seem to be meant to be inferred from the arguments, but what if a type parameter value cannot be inferred from the arguments, like this?

'theBiasPlanet/coreUtilitiesTests/templatesTest1/ClassB.hpp'

@C++ Source Code
#ifndef __theBiasPlanet_coreUtilitiesTests_templatesTest1_ClassB_hpp__
	#define __theBiasPlanet_coreUtilitiesTests_templatesTest1_ClassB_hpp__
	
	namespace theBiasPlanet {
		namespace coreUtilitiesTests {
			namespace templatesTest1 {
				template <typename T> class ClassB {
					public:
					    ClassB ();
					    template <typename U> ClassB ();
				};
			}
		}
	} 
#endif

Meaningless? Not necessarily: the type "U" may be being used meaningfully inside the constructor template implementation.

Obviously, the Visual C++ way does not ever allow any explicit instantiation of the constructor template.

The explicitly-specifying-the-type-parameter-values way can instantiate the constructor template, but, in fact, the constructor template cannot be used anyway.

That is because, in fact, how can it be used? . . . C++ does not allow this.

@C++ Source Code
	ClassB <int> <double> l_classB (); // This is not allowed, where 'double' is meant to be a specification of 'U'.

The C++ standard's claim seems to be "It just cannot be done because of the way in which constructors are called.", but I think that it is just a defect of the C++ standard: the C++ standard can just contrive a way, because you are the master!

Of course, I can add a dummy argument if I am really pressed so, but it would be quite ugly.

I do not know whether the Visual C++ way is more compliant to the C++ standard or not, but anyway, it is unreasonable, being asymmetric with expressions for non-constructor method templates (the C++ standard seems to be claiming that the seemingly-function-name of any constructor is not really any function name, but such a claim seems just arbitrary, and while declarations of constructor templates are exactly like those of non-constructor ones, why do explicit instantiations of constructor templates have to be different?).


References


<The previous article in this series | The table of contents of this series | The next article in this series>