I'm using explicit template specialization to initialize a std::vector with information but only for a specific type of std::vector, thus the explicit specialization. Within the constructor, if I try to call push_back or any other existing function in std::vector, compilation fails. What is the problem and how do I fix it?
simplified example:
namespace std
{
template<>
class vector<int>
{
public:
vector(void)
{
int value = 5;
push_back(value);
}
};
}
compiler message:
In constructor 'std::vector<int>::vector()':
error: 'push_back' was not declared in this scope
push_back(value);
^
Explicit specializations are completely different classes that are separate from the primary template. You have to rewrite everything.
In normal situations where you control the primary template, you would typically have some sort of common base class or base class template to collect common structures.
With a given library, it is generally a very bad idea to add specializations (unless the library explicitly says it's OK). With the C++ standard library, this is outright undefined behaviour.
(The main problem is that other translation units may be using the template instantiation which you're specializing without seeing your specialization, which violates the one-definition rule.)
Template specializations are unrelated types from both the primary template and any other specialization. It is unclear what you are attempting to do, as it is also illegal to provide specializations of templates in the std namespace unless the specialization uses your own user defined type.
If you can explain the problem to solve, you might get other options, like specializing a member function rather than the template itself...
Related
Let's say I have this:
template<typename T>
class my_template {...};
Now, users are expected to be able to specialize my_template for their own types. And they will pass those types to some API functions of mine, which will use properties of my_template<T> to do stuff.
So at some point in my code, I have a my_template<T>. I want a meta-function of some kind which takes my_template<T> and results in a compile-time value of true if my_template<T> is a user-provided specialization (partial or explicit) and false if it isn't.
The most obvious solution is to shove a private member alias, or some other concept-detectable private declaration, into the primary my_template definition, and rely on that not being present in user-provided specializations. However, a user could forge an explicit specialization by providing an appropriate definition. So this isn't foolproof.
This question is not sophistry. The C++20 specification has a meta-function ITER_CONCEPT(I), which has different internal behavior based on whether std::iterator_traits<I> is from the primary template or a user-provided specialization. Of course, being the standard library, they can create an identifier prefixed with __ as a member of the primary template and thereby declare any attempted forgery from user-space to be undefined behavior.
Is this a thing only a compiler/standard library implementation can do in a foolproof, or is it possible to do this in C++20?
The most obvious solution is to shove a private member alias, or some other concept-detectable private declaration, into the primary my_template definition, and rely on that not being present in user-provided specializations. However, a user could forge an explicit specialization by providing an appropriate definition. So this isn't foolproof.
That's basically it, yep. For instance, libstdc++'s iterator traits has its primary class template inherit from a hidden base class template, and then checks for inheritance from that base.
Yes, a user could forge an explicit specialization by providing an appropriate definition - but, like, don't. That isn't something you would do by accident, that's explicitly and pointlessly malicious, and the typical saying is that the library and the language defend against Murphy, not Machiavelli.
With Modules, you can make it even harder for the user to be explicitly malicious by exporting the primary template but not actually exporting the base class that you're using to check if the class template was specialized:
export module std;
namespace std {
template <typename T> struct __iterator_traits { };
template <typename T>
export struct iterator_traits : __iterator_traits { };
}
Now the user can't even name std::__iterator_traits in order to break the library. Perhaps reflection will still give them a way to do so (assuming those things are still accessible), but now they'd really be jumping through a lot of hoops.
Speaking of Reflection, part of the currently-specified API (P1240) includes the functions is_specialization, is_partial_specialization, and is_explicit_specialization. If those mean what I think they mean, then when we eventually get reflection, then the library wouldn't have do use these magic base / magic member hacks and could just directly check to see if the provided specialization was a partial or explicit specialization or not. I figure the library should probably add is_primary_specialization for completeness.
Let's say I have this:
template<typename T>
class my_template {...};
Now, users are expected to be able to specialize my_template for their own types. And they will pass those types to some API functions of mine, which will use properties of my_template<T> to do stuff.
So at some point in my code, I have a my_template<T>. I want a meta-function of some kind which takes my_template<T> and results in a compile-time value of true if my_template<T> is a user-provided specialization (partial or explicit) and false if it isn't.
The most obvious solution is to shove a private member alias, or some other concept-detectable private declaration, into the primary my_template definition, and rely on that not being present in user-provided specializations. However, a user could forge an explicit specialization by providing an appropriate definition. So this isn't foolproof.
This question is not sophistry. The C++20 specification has a meta-function ITER_CONCEPT(I), which has different internal behavior based on whether std::iterator_traits<I> is from the primary template or a user-provided specialization. Of course, being the standard library, they can create an identifier prefixed with __ as a member of the primary template and thereby declare any attempted forgery from user-space to be undefined behavior.
Is this a thing only a compiler/standard library implementation can do in a foolproof, or is it possible to do this in C++20?
The most obvious solution is to shove a private member alias, or some other concept-detectable private declaration, into the primary my_template definition, and rely on that not being present in user-provided specializations. However, a user could forge an explicit specialization by providing an appropriate definition. So this isn't foolproof.
That's basically it, yep. For instance, libstdc++'s iterator traits has its primary class template inherit from a hidden base class template, and then checks for inheritance from that base.
Yes, a user could forge an explicit specialization by providing an appropriate definition - but, like, don't. That isn't something you would do by accident, that's explicitly and pointlessly malicious, and the typical saying is that the library and the language defend against Murphy, not Machiavelli.
With Modules, you can make it even harder for the user to be explicitly malicious by exporting the primary template but not actually exporting the base class that you're using to check if the class template was specialized:
export module std;
namespace std {
template <typename T> struct __iterator_traits { };
template <typename T>
export struct iterator_traits : __iterator_traits { };
}
Now the user can't even name std::__iterator_traits in order to break the library. Perhaps reflection will still give them a way to do so (assuming those things are still accessible), but now they'd really be jumping through a lot of hoops.
Speaking of Reflection, part of the currently-specified API (P1240) includes the functions is_specialization, is_partial_specialization, and is_explicit_specialization. If those mean what I think they mean, then when we eventually get reflection, then the library wouldn't have do use these magic base / magic member hacks and could just directly check to see if the provided specialization was a partial or explicit specialization or not. I figure the library should probably add is_primary_specialization for completeness.
I'm reading C++ Primer, and it says:
"If a member function isn't used, it is not instantiated. The fact that members are instantiated only if we use them lets us instantiate a class with a type that may not meet the requirements for some of the template’s operations."
I don't know why this is a problem. If some operations are required, why doesn't compiler instantiate those operations? Can someone give an example?
That's an ease-of-use feature, not a pitfall.
Lazy instantiation serves to simplify templates. You can implement the set of all possible member functions that any specialization might have, even if some of the functions don't work for some specializations.
It also reduces compile time, since the compiler never needs to instantiate what you don't use.
To prevent lazy instantiation, use explicit instantiation:
template class my_template< some_arg >;
This will immediately instantiate all the members of the class (except members which are templates, inherited, or not yet defined). For templates that are slow to compile, you can do the above in one source file (translation unit) and then use the linker to bypass instantiation in other source files, by putting a declaration in the header:
extern template class my_template< some_arg >;
A colleague of mine told me about a little piece of design he has used with his team that sent my mind boiling. It's a kind of traits class that they can specialize in an extremely decoupled way.
I've had a hard time understanding how it could possibly work, and I am still unsure of the idea I have, so I thought I would ask for help here.
We are talking g++ here, specifically the versions 3.4.2 and 4.3.2 (it seems to work with both).
The idea is quite simple:
1- Define the interface
// interface.h
template <class T>
struct Interface
{
void foo(); // the method is not implemented, it could not work if it was
};
//
// I do not think it is necessary
// but they prefer free-standing methods with templates
// because of the automatic argument deduction
//
template <class T>
void foo(Interface<T>& interface) { interface.foo(); }
2- Define a class, and in the source file specialize the interface for this class (defining its methods)
// special.h
class Special {};
// special.cpp
#include "interface.h"
#include "special.h"
//
// Note that this specialization is not visible outside of this translation unit
//
template <>
struct Interface<Special>
{
void foo() { std::cout << "Special" << std::endl; }
};
3- To use, it's simple too:
// main.cpp
#include "interface.h"
class Special; // yes, it only costs a forward declaration
// which helps much in term of dependencies
int main(int argc, char* argv[])
{
Interface<Special> special;
foo(special);
return 0;
};
It's an undefined symbol if no translation unit defined a specialization of Interface for Special.
Now, I would have thought this would require the export keyword, which to my knowledge has never been implemented in g++ (and only implemented once in a C++ compiler, with its authors advising anyone not to, given the time and effort it took them).
I suspect it's got something to do with the linker resolving the templates methods...
Do you have ever met anything like this before ?
Does it conform to the standard or do you think it's a fortunate coincidence it works ?
I must admit I am quite puzzled by the construct...
Like #Steward suspected, it's not valid. Formally it's effectively causing undefined behavior, because the Standard rules that for a violation no diagnostic is required, which means the implementation can silently do anything it wants. At 14.7.3/6
If a template, a member template or the member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
In practice at least on GCC, it's implicitly instantiating the primary template Interface<T> since the specialization wasn't declared and is not visible in main, and then calling Interface<T>::foo. If its definition is visible, it instatiates the primary definition of the member function (which is why when it is defined, it wouldn't work).
Instantiated function name symbols have weak linkage because they could possibly be present multiple times in different object files, and have to be merged into one symbol in the final program. Contrary, members of explicit specializations that aren't templates anymore have strong linkage so they will dominate weak linkage symbols and make the call end up in the specialization. All this is implementation detail, and the Standard has no such notion of weak/strong linkage. You have to declare the specialization prior to creating the special object:
template <>
struct Interface<Special>;
The Standard lays it bare (emphasize by me)
The placement of explicit specialization declarations for function templates, class templates, member functions of class templates, static data members of class templates, member classes of class templates, member class templates of class templates, member function templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, member class templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
Thats pretty neat. I'm not sure if it is guaranteed to work everywhere though. It looks like what they're doing is having a deliberately undefined template method, and then defining a specialization tucked away in its own translation unit. They're depending on the compiler using the same name mangling for both the original class template method and the specialization, which is the bit I think is probably non-standard. The linker will then look for the method of the class template, but instead find the specialization.
There are a few risks with this though. No one, not even the linker, will pick up multiple implementations of the method for example. The template methods will be marked selectany because template implies inline so if the linker sees multiple instances, instead of issuing an error it will pick whichever one is most convenient.
Still a nice trick though, although unfortunately it does seem to be a lucky coincidence that it works.
It is my understanding that either a declaration or typedef of a specialization ought to cause a template class to be instantiated, but this does not appear to be happening with gcc. E.g. I have a template class, template class Foo {};
I write
class Foo<double>;
or
typedef Foo<double> DoubleFoo;
but after compilation the symbol table of the resulting object file does not contain the members of Foo.
If I create an instance:
Foo<double> aFoo;
then of course the symbols are all generated.
Has anyone else experienced this and/or have an explanation?
The syntax for explicit instantiation is
template class Foo<double>;
See C++03 §14.7.2.
Hoping the functions get generated and linked, but not stripped after creating, but not using, an instance (the most minimal implicit instantiation), is quite a gamble.
You are talking about implicit instantiation. But that does only happen if the completenes of the class type would affect semantics of the program.
In your case, the class type doesn't need to be complete because the type you typedef can stay incomplete (class body is not needed, so there is no need to instantiate it). To illustrate, you can also say typedef class MyFunnyThing type; in a statement of its own, without ever defining that class anywhere.
If you create an object, the type of it has to be complete, and so the class template then is implicitly instantiated. Please note that implicit instantiation of a class template will not implicitly instantiate the member function or static datamember definitions, unless they are explicitly used elsewhere.
Also, to declare a specialization of a class-template, the whole point is to prevent an instantiation to happen, to tell the compiler "don't instantiate, because later i specialize it explicitly". The declaration if your specialization also misses a template<> in front of it.