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
- Orientation
- Main Body
- 1: Meeting a Set of Enigmatic Errors for an Explicit Instantiation of a Class Constructor Template
- 2: A Solution and Reasoning
Starting Context
- The reader has a basic knowledge on C++.
- The reader understands what C++ template is, and the distinction between template instantiation (explicit or implicit) and inlining.
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 DirectionHypothesizer 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?).