I read the C ++ 14 section in templates, trying to improve my understanding of the subject and came across this particular rule:
ยง 14.1
12 The template parameter should not be assigned the default arguments by two different declarations in the same area.
[Example:
template<class T = int> class X; template<class T = int> class X { /โ... โ/ };
- end of example]
In my (relatively uninformed) reading, the specification of "the same area" implies the ability to declare templates in different areas where they are defined.
According to this article about Dr. Dobbs
C ++ identifies five kinds of scope: function, prototype functions, local, namespace and class.
From them I understand that:
- and (I assume the function prototype, since it extends past functions only to declarations) scope cannot contain template declarations
- the local area falls within the scope of the function and, therefore, has the same limitations as above
- you cannot (re) declare any member of a class outside the declaration of that class.
Thus, the potential odd case of resolving declarations outside a specific area (potentially with changed default arguments depending on the scope!) Seems to fall directly onto the shoulders of the namespace area. I experimented a bit:
[ Coliru ]
Command:
g++ -std=c++1z -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Code:
#include <iostream> namespace math{ template <int I, int J> struct Plus{ constexpr static int Value_ = I + J; }; template <int I, int J = 5> struct Minus; // template declaration. } // global-scope template declaration? //template <int I, int J> //struct math::Minus; // error: does not name a type (if no declaration @ line 9) // error: invalid use of math::Minus w/o argument list // (if declaration @ line 9) namespace math{ template <int I, int J> struct Minus{ static int value(); }; namespace{ // anonymous namespace //template <int I, int J = 5> //struct Minus; compiles, but is a declaration of another class, // which I assume hides the math scope class // error: incomplete type--I assume this means the above // doesn't declare math::Minus, but math::<anon>::Minus //constexpr int twominus5= Minus<2>::value(); } // end anonymous namespace } // end math namespace //template <int I, int J> //class math::Minus; // error: invalid use of math::Minus w/o argument list template <int I, int J> int math::Minus<I,J>::value(){return I - J;} int main() { std::cout << math::Minus<5,1>::value() << std::endl << math::Minus<0>::value() << std::endl; }
Output:
4 -5
... and the declaration rules seemed to match what I expected before reading this little snippet of the standard. Clearly, my understanding is somewhere wrong. Is this with my initial reading of the standard argument argument declaration default argument for the standard C ++ template, as I suspect, or did I skip some method of declaring the templates outside their own scope?
Naturally, an odd corner of the language like this (if it really exists) should be used with restraint and with great care, especially since it will change the behavior of partially defined patterns in other places depending on the most applicable area (can this cause would the full-resolved name otherwise be resolved in the area without default declarations if there were default parameters in the template definition area?), but it aroused my curiosity.
I will use pseudonyms regardless of the fact that this is less ambiguous for everyone involved, but as I said above: I am now wondering if this is a feature of an odd language that I could not fully use for intentional use, or a non-function I just imagined.