How to force a template code creation without creating object instance? - c++

I have a template class that is only valid for couple of template parameters:
doIt.h:
// only int and float are valid T
template <typename T>
class doer
{
public:
void doIt();
}
I want to hide the implementation inside the .cpp file (for faster compile and also because its proprietary):
doIt.cpp:
template <>
void doer<T>::doIt() { /* how to do it */ }
... and use it as follows: use.cpp:
int main( int, char** )
{
doer<int>::doIt()
}
The above fails to link because the implementation of void doer::doIt(void) was never in scope at the place where it was called.
I can force the code to be generated into doItv2.obj, as follows:
doIt_v2.cpp:
template <>
void doer<T>::doIt() { /* how to do it */ }
doer<int> a;
doer<real> b;
but this causes a variety of headaches (dynamic memory allocation before main is entered) and I actually don't want to make an instance -- I just want the object code for the template instantiations to be generated.
Any ideas?

See the article How to Organize Template Source Code. I think you are after the second method described there: explicit template instantiation.

Related

Is there a way to call an initialization function only when specific class template (specialization) is instantiated?

I'm designing a wrapper over various computational functionality. Some of the underlying backends require some init functions to be called before any other API calls are made. I could use some static variable that is initialized before main, and wrap it in some function as described here so that I can catch any errors produced during initialization.
I wonder if there is a better way to handle this. Note that there will never be an instance of the class template, as everything is either a typedef or static member.
To address the problem of initializing the API only for some specializations, and of initializing it only once, I'd do something like this:
#include <iostream>
template <typename T>
struct Wrapper
{
// class who will be statically instantiated
struct CtorClass
{
CtorClass()
{
std::cout << "Init\n";
}
};
static CtorClass static_ctor;
static void compute1(){}
static void compute2(){}
};
// definition for template static member cons
template <typename T>
typename Wrapper<T>::CtorClass Wrapper<T>::static_ctor;
struct NeedInit{};
// you will have to use static_ctor in every funcition of the
template <>
void Wrapper<NeedInit>::compute1()
{
static_ctor;
}
template <>
void Wrapper<NeedInit>::compute2()
{
static_ctor;
}
int main()
{
Wrapper<int>::compute1();
Wrapper<int>::compute2();
Wrapper<NeedInit>::compute1();
Wrapper<NeedInit>::compute2();
}
Sadly, this way you have to use static_ctor in every function specialization that belongs to a Wrapper<NeedInit> class. But you wouldn't need to check for the initialization to have already been called.
Then, you could catch errors like you said.

Why are function template specializations not allowed inside a class?

After having found answers to many of my questions on stackoverflow, I have now come up against a question of which I can't find the answer and I hope that someone is willing to help me!
My problem is that I want to do an explicit templatization of a function inside a class in C++. My compiler (g++) and a look in the C++ standard (§14.7.3) tells me that this specialization has to be done in the namespace in which the class is declared. I understand that this implies that I cannot put the specialization inside the class, but I don't see the point of this restriction! Does anyone know if there is a good reason for not letting the specializations be made inside the class?
I know that there are workarounds, e.g. to put the function inside a struct, but I want to understand why the language has this design. If there is a good reason for not allowing specialized functions inside the class, I guess I should know it before trying to work around it.
Thanks in advance!
To make my question a little bit more precise: Here is some code from a test example which illustrates what I want to do:
#include <cstdio>
namespace MalinTester {
template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest() {
privateVariable = 5;
};
virtual ~SpecializationTest() {};
void execute() {
execute<DIMENSIONALITY>();
};
private:
int privateVariable;
template <size_t currentDim>
static void execute() {
printf("This is the general case. Current dim is %d. The private variable is %d.\n", currentDim, privateVariable);
execute<currentDim-1>();
}
template <>
static void execute<0>() {
printf("This is the base case. Current dim is 0.\n");
}
};
This is not possible; g++ says:
SpecializationTest_fcn.h:27: error: explicit specialization in non-namespace scope ‘class MalinTester::SpecializationTest<DIMENSIONALITY>’
SpecializationTest_fcn.h:28: error: template-id ‘execute<0>’ in declaration of primary template
If I put the function execute outside the class, in the name space MalinTester, it will look like this:
#include <cstdio>
namespace MalinTester {
template <size_t DIMENSIONALITY> class SpecializationTest {};
template <size_t currentDim>
void execute() {
printf("This is the general case. Current dim is %d. The private variable is %d.\n", currentDim, privateVariable);
execute<currentDim-1>();
}
template <>
void execute<0>() {
printf("This is the base case. Current dim is 0.\n");
}
template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest() {};
virtual ~SpecializationTest() {};
void execute() {
MalinTester::execute<DIMENSIONALITY>();
};
private:
int privateVariable = 5;
};
};
};
and I cannot use privatevariable in the templatized versions of execute, as it is private in the class. I really want it private, as I want to have my data encapsulated as far as possible.
Of course I can send privateVariable as an argument to the function, but I think it would be more beautiful to avoid this, and what I really wonder is if there is a good reason for the C++ standard not to allow explicit specialization as in the first code example above.
#Arne Mertz: This is the workaround I have tried, but it doesn't allow using privateVariable either. And most of all, I wonder if it is a good idea to do like this. As I'm not allowed to make specializations of member functions, maybe I shouldn't do specializations of functions encapsulated in structs inside the class either.
#include <cstdio>
namespace MalinTester {
template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest() {
privateVariable = 5;
};
virtual ~SpecializationTest() {};
void execute() {
Loop<DIMENSIONALITY, 0>::execute();
};
private:
int privateVariable;
template <size_t currentDim, size_t DUMMY>
struct Loop {
static void execute() {
printf("This is the general case. Current dim is %d.\n", currentDim);
Loop<currentDim-1, 0>::execute();
}
};
template <size_t DUMMY>
struct Loop<0, DUMMY> {
static void execute() {
printf("This is the base case. Current dim is 0.\n");
}
};
};
};
Base specialization:
In .h:
template <class T>
class UISelectorSlider : public UISelectorFromRange<T> {
public:
UISelectorSlider();
virtual ~UISelectorSlider();
private:
float width;
float getPositionFromValue(T value);
};
In .cpp under same namespace:
template <>
float UISelectorSlider<MVHue>::getPositionFromValue(MVHue value)
{
return width * (float)value / 360.0;
}
If you want specialized function within specialized class:
Inside class add (.h) (private function):
private:
template <int I>
void foo();
Specialization inside .cpp:
template <>
template <>
void UISelectorSlider<MVHue>::foo<3>()
{
// you can access private fields here
}
UPDATE:
But you cant write something like this:
template <class T>
template <>
void UISelectorSlider<T>::foo<3>()
{
// you can access private fields here
}
You will get: error: enclosing class templates are not explicitly specialized.
It does not matter is this definition inside class or in namespace. The point is that this is not exact partial specialization - this function does not have defined context class (which members you want to call). In other words - when you specialize member you actually try specialize the whole containing class, but not the member itself. And compiler cant do that because class is not yet defined completely. So this is restriction by template design. And if it actually worked - templates would be full equivalent to simple macros.
(And you probably can will solve your task with some macro magic.)

Templated classes with pimpl idiom incorrect

As described in the MSDN library here I wanted to experiment a bit with the pimpl idiom. Right now I have a Foo.hpp with
template<typename T>
class Foo {
public:
typedef std::shared_ptr<Foo<T>> Ptr;
Foo();
private:
class Impl;
std::unique_ptr<Impl> pImpl;
};
where the T parameter isn't used yet. The implementation is stored in Foo.cpp
template<typename T>
class Foo<T>::Impl {
public:
int m_TestVar;
};
template<typename T>
Foo<T>::Foo() : pImpl(new Impl) {
this->pImpl->m_TestVar = 0x3713;
}
Currently the compiler has two errors and one warning:
use of undefined type 'Foo<T>::Impl'; ... vc\include\memory in line 1150
can't delete an incomplete type; ... vc\include\memory in line 1151
deletion of pointer to incomplete type 'Foo<T>::Impl'; no destructor called; ... vc\include\memory in line 1152
What is the concflict here and how could I resolve it?
Edit. Removed the call to std::make_shared - copy&paste fail based on one old version.
I have had a similar issue - we've a base class in our system called NamedComponent and I wanted to create a template which takes an existing named component and converts it into a pimpl facade.
What I did was separate the template into a header and an inline file, and create a function to cause the template to be instantiated. This allows the implementation to be in a library, with the template instantiations of the facade with that implementation, and for the client to be able to use the facade based on the template and a forward declaration of the implementation.
header 'Foo.h':
template<class T> class Foo
{
public:
Foo ();
virtual ~Foo();
private:
T *impl_;
public:
// forwarding functions
void DoIt();
};
inline functions 'Foo.inl':
#include "Foo.h"
template<class T> Foo<T>::Foo() :
impl_ ( new T )
{
}
template<class T> Foo<T>::~Foo()
{
delete impl_;
}
// forwarding functions
template<class T> void Foo<T>::DoIt()
{
impl_ -> DoIt();
}
// force instantiation
template<typename T>
void InstantiateFoo()
{
Foo<T> foo;
foo.DoIt();
}
implementation cpp file - include the template inline functions, define the implementation, reference the instantiation function:
#include "Foo.inl"
class ParticularImpl {
public:
void DoIt() {
std::cout << __FUNCTION__ << std::endl;
}
};
void InstantiateParticularFoo() {
InstantiateFoo<ParticularImpl>();
}
client cpp file - include the template header, forward declare the implementation and use the pimpl facade:
#include "Foo.h"
class ParticularImpl;
int main () {
Foo<ParticularImpl> bar;
bar.DoIt();
}
You may have to fiddle with the InstantiateFoo function's contents to force the compiler to instantiate all functions - in my case, the base called all the pimpl's functions in template methods so once one was referenced, they all were. You don't need to call the Instantiate functions, just link to them.
IMHO PIMPL doesn't make much sense with templates, unless you know all possible template parameters and that set is fairly small. The problem is, that you will either have the Impl implementation in the header file otherwise, as has been noted in the comments. If the number of possible T parameters is small, you still can go with the separation, but you'll need to declare the specialisations in the header and then explicitly instantiate them in the source file.
Now to the compiler error: unique_ptr<Impl> requires the definition of Impl to be available. You'll need to directly use new and delete in the ctor Foo::Foo and dtor Foo::~Foo, respectively instead and drop the convenience/safety of smart pointers.

C++ Templated function calling a managed function

I'm trying to build a wrapper around a managed class so I can call it from native code.
Here is the managed function :
void MyManagedFunction(MyStruct iStruct)
{
// Code according to what are the types of the 2 MyStruct members
}
struct MyStruct
{
public MyStruct(Object iValue1, Object iValue2) : this()
{
Value1 = iValue1; // Often contains DateTime::Now
Value2 = iValue2;
}
public Object Value1;
public Object Value2;
}
In my case, Value1 will almost always be System::DateTime::Now and the Value2 will almost always be a common data type (int, double, float, string, bool). I thought of making two templated function in the wrapper.
In the wrapper's .h I have the following :
#ifdef MYWRAPPER_EXPORTS
# define MYWRAPPER __declspec(dllexport)
#else
# define MYWRAPPER __declspec(dllimport)
#endif
class MYWRAPPER MyWrapper
{
public:
MyWrapper();
~MyWrapper();
template <class T> void MyNativeFunction(T iParam1)
{
MyStruct^ wStruct = gcnew MyStruct(System::DateTime::Now, iParam1);
//The class containing the managed function is a singleton
MyManagedClass::Instance->MyManagedFunction(wStruct);
}
template <class T, class W> void MyNativeFunction(T iParam1, W iParam2)
{
MyStruct^ wStruct = gcnew MyStruct(iParam1, iParam2);
//The class containing the managed function is a singleton
MyManagedClass::Instance->MyManagedFunction(wStruct);
}
};
This wrapper compiled without problem. The problem obviously occurred when I included the .h in the purely native code. Since I can't hide the content of the templated function, I have managed stuff visible on the native side which prevent the native code from compiling.
I was wondering if there was a workaround in order to achieve this. I don't mind if I'm limited into using only primitive types as parameters for the function. The best thing is if I was able to simply hide the content of the templated function in the native code so it only knows about the signature
Here's what I've tried/considered so far :
Converting the parameters to void* and call a function in which would call the managed one. By doing so, I can't cast the void* back to an object since I lose its type and using typeid to get the 'T' or 'W' type doesn't help since it vary from a compiler to another.
Overloading the function for every types I want to use. This is what I'll most likely use if I doesn't find a better solution. The problem is it means alot of overloading (especially for the 2 parameters function considering the number of combination)
If you know all the types your template will take, you can force instantiate it with those variables and thus put the code for the template functions in the source file instead of a header.
You can look at the example provided in Storing C++ template function definitions in a .CPP file
As he says you can do as below (copy-paste alert):
.h file
class foo
{
public:
template <typename T>
void do(const T& t);
};
.cpp file
template <typename T>
void foo::do(const T& t)
{
// Do something with t
}
template void foo::do<int>(const int&);
template void foo::do<std::string>(const std::string&);

Is it possible trigger a compiler / linker error if a template has not been instantiated with a certain type?

Follow-up question to [Does casting to a pointer to a template instantiate that template?].
The question is just as the title says, with the rest of the question being constraints and usage examples of the class template, aswell as my tries to achieve the goal.
An important constraint: The user instantiates the template by subclassing my class template (and not through explicitly instantiating it like in my tries below). As such, it is important to me that, if possible, the user doesn't need to do any extra work. Just subclassing and it should work (the subclass actually registers itself in a dictionary already without the user doing anything other than subclassing an additional class template with CRTP and the subclass is never directly used by the user who created it). I am willing to accept answers where the user needs to do extra work however (like deriving from an additional base), if there really is no other way.
A code snippet to explain how the class template is going to be used:
// the class template in question
template<class Resource>
struct loader
{
typedef Resource res_type;
virtual res_type load(std::string const& path) const = 0;
virtual void unload(res_type const& res) const = 0;
};
template<class Resource, class Derived>
struct implement_loader
: loader<Resource>
, auto_register_in_dict<Derived>
{
};
template<class Resource>
Resource load(std::string const& path){
// error should be triggered here
check_loader_instantiated_with<Resource>();
// search through resource cache
// ...
// if not yet loaded, load from disk
// loader_dict is a mapping from strings (the file extension) to loader pointers
auto loader_dict = get_all_loaders_for<Resource>();
auto loader_it = loader_dict.find(get_extension(path))
if(loader_it != loader_dict.end())
return (*loader_it)->load(path);
// if not found, throw some exception saying that
// no loader for that specific file extension was found
}
// the above code comes from my library, the code below is from the user
struct some_loader
: the_lib::implement_loader<my_fancy_struct, some_loader>
{
// to be called during registration of the loader
static std::string extension(){ return "mfs"; }
// override the functions and load the resource
};
And now in tabular form:
User calls the_lib::load<my_fancy_struct> with a resource path
Inside the_lib::load<my_fancy_struct>, if the resource identified by the path isn't cached already, I load it from disk
The specific loader to be used in this case is created at startup time and saved in a dictionary
There is a dictionary for every resource type, and they map [file extension -> loader pointer]
If the dictionary is empty, the user either
didn't create a loader for that specific extension or
didn't create a loader for that specific resource
I only want the first case to have me throw a runtime exception
The second case should be detected at compile / link time, since it involves templates
Rationale: I'm heavily in favor of early errors and if possible I want to detect as many errors as possible before runtime, i.e. at compile and link time. Since checking if a loader for that resource exists would only involve templates, I hope it's possible to do this.
The goal in my tries: Trigger a linker error on the call to check_error<char>.
// invoke with -std=c++0x on Clang and GCC, MSVC10+ already does this implicitly
#include <type_traits>
// the second parameter is for overload resolution in the first test
// literal '0' converts to as well to 'void*' as to 'foo<T>*'
// but it converts better to 'int' than to 'long'
template<class T>
void check_error(void*, long = 0);
template<class T>
struct foo{
template<class U>
friend typename std::enable_if<
std::is_same<T,U>::value
>::type check_error(foo<T>*, int = 0){}
};
template struct foo<int>;
void test();
int main(){ test(); }
Given the above code, the following test definition does achieve the goal for MSVC, GCC 4.4.5 and GCC 4.5.1:
void test(){
check_error<int>(0, 0); // no linker error
check_error<char>(0, 0); // linker error for this call
}
However, it should not do that, as passing a null pointer does not trigger ADL. Why is ADL needed? Because the standard says so:
§7.3.1.2 [namespace.memdef] p3
[...] If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup or by qualified lookup until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). [...]
Triggering ADL through a cast, as in the following definition of test, achieves the goal on Clang 3.1 and GCC 4.4.5, but GCC 4.5.1 already links fine, as does MSVC10:
void test(){
check_error<int>((foo<int>*)0);
check_error<char>((foo<char>*)0);
}
Sadly, GCC 4.5.1 and MSVC10 have the correct behaviour here, as discussed in the linked question and specifically this answer.
The compiler instatiates a template function whenever it is referenced and a full specification of the template is available. If none is available, the compiler doesn't and hopes that some other translation unit will instantiate it. The same is true for, say, the default constructor of your base class.
File header.h:
template<class T>
class Base
{
public:
Base();
};
#ifndef OMIT_CONSTR
template<class T>
Base<T>::Base() { }
#endif
File client.cc:
#include "header.h"
class MyClass : public Base<int>
{
};
int main()
{
MyClass a;
Base<double> b;
}
File check.cc:
#define OMIT_CONSTR
#include "header.h"
void checks()
{
Base<int> a;
Base<float> b;
}
Then:
$ g++ client.cc check.cc
/tmp/cc4X95rY.o: In function `checks()':
check.cc:(.text+0x1c): undefined reference to `Base<float>::Base()'
collect2: ld returned 1 exit status
EDIT:
(trying to apply this to the concrete example)
I'll call this file "loader.h":
template<class Resource>
struct loader{
typedef Resource res_type;
virtual res_type load(std::string const& path) const = 0;
virtual void unload(res_type const& res) const = 0;
loader();
};
template<class Resource>
class check_loader_instantiated_with : public loader<Resource> {
virtual Resource load(std::string const& path) const { throw 42; }
virtual void unload(Resource const& res) const { }
};
template<class Resource>
Resource load(std::string const& path){
// error should be triggered here
check_loader_instantiated_with<Resource> checker;
// ...
}
And another file, "loader_impl.h":
#include "loader.h"
template<class Resource>
loader<Resource>::loader() { }
This solution has one weak point that I know of. Each compilation unit has a choice of including either only loader.h or loader_impl.h. You can only define loaders in compilation units that include loader_impl, and in those compilation units, the error checking is disabled for all loaders.
After thinking a bit about your problem, I don't see any way to achieve this. You need a way to make the instantiation "export" something outside the template so that it can be accessed without referencing the instantiation. A friend function with ADL was a good idea, but unfortunately it was shown that for ADL to work, the template had to be instantiated. I tried to find another way to "export" something from the template, but failed to find one.
The usual solution to your problem is to have the user specializes a trait class:
template < typename Resource >
struct has_loader : boost::mpl::false_ {};
template <>
struct has_loader< my_fancy_struct > : boost::mpl::true_ {};
To hide this from the user, you could provide a macro:
#define LOADER( loaderName, resource ) \
template <> struct has_loader< resource > : boost::mpl::true_ {}; \
class loaderName \
: the_lib::loader< resource > \
, the_lib::auto_register_in_dict< loaderName >
LOADER( some_loader, my_fancy_struct )
{
public:
my_fancy_struct load( std::string const & path );
};
It is up to you to determine whether having this macro is acceptable or not.
template <class T>
class Wrapper {};
void CheckError(Wrapper<int> w);
template <class T>
class GenericCheckError
{
public:
GenericCheckError()
{
Wrapper<T> w;
CheckError(w);
}
};
int main()
{
GenericCheckError<int> g1; // this compiles fine
GenericCheckError<char> g2; // this causes a compiler error because Wrapper<char> != Wrapper<int>
return 0;
}
Edit:
Alright this is as close as I can get. If they subclass and either instantiate OR define a constructor that calls the parent's constructor, they will get a compiler error with the wrong type. Or if the child class is templatized and they subclass and instantiate with the wrong type, they will get a compiler error.
template <class T> class Wrapper {};
void CheckError(Wrapper<int> w) {}
template <class T>
class LimitedTemplateClass
{
public:
LimitedTemplateClass()
{
Wrapper<T> w;
CheckError(w);
}
};
// this causes no compiler error
class UserClass : LimitedTemplateClass<int>
{
UserClass() : LimitedTemplateClass<int>() {}
};
// this alone (no instantiation) causes a compiler error
class UserClass2 : LimitedTemplateClass<char>
{
UserClass2() : LimitedTemplateClass<char>() {}
};
// this causes no compiler error (until instantiation with wrong type)
template <class T>
class UserClass3 : LimitedTemplateClass<T>
{
};
int main()
{
UserClass u1; // this is fine
UserClass2 u2; // this obviously won't work because this one errors after subclass declaration
UserClass3<int> u3; // this is fine as it has the right type
UserClass3<char> u4; // this one throws a compiler error
return 0;
}
Obviously you can add other accepted types by defining additional CheckError functions with those types.