I am working on a project that has a lot of trait types. If I compile every trait in the same code base, the released binary would be quite big.
I am thinking about to use macro to build a binary for each specific trait --- from a business logic perspective, this makes perfect sense.
However, I realized that, if I want to cut down the code base, I need to have this long if/elif pile at the end of each template cpp file. This sounds like a very tedious thing to do.
I am wondering if you have encountered this kind of problem before, what's the most neat solution here?
#include "MyTraits.hpp"
#include "Runner.hpp"
int main(){
#if defined USE_TRAIT_1
Runner<Trait1> a;
#elif defined USE_TRAIT_2
Runner<Trait2> a;
#elif defined USE_TRAIT_3
Runner<Trait3> a;
#endif
return 0;
}
If you want to explicity instanciate templates in specific compilation units you should use the extern template keyword.
// Runner.hpp
//define your template class
template <class runner_trait>
class Runner {
...
};
//This tells the compiler to not instanciate the template,
// if it is encounterd, but link to it from a compilation unit.
// If it is not found, you will get a linker errer.
extern template Runner<Trait1>;
extern template Runner<Trait2>;
extern template Runner<Trait3>;
Runner_trait1.cpp
// the template class keyword tell the compiler to instanciate the template in this compilation unit.
template class Runner<Trait1>;
// The files for Runner_trait2.cpp and Runner_trait3.cpp look identical,
// except for the trait after Runner
I'm not entirely sure that my answer will address the root cause of the problem. But the proposed solution may at least look a bit more "neat".
The basic idea behind the proposal by #JeffCharter makes sense, but I don't like the idea of embedding the code (in this case type names) into the makefile. So I elaborated on it a bit, with the following goals in mind:
Make the contents of main() short and easy to understand
Avoid polluting the makefile
Avoid the macro usage to the most possible extent
I ended up with the following solution which requires a single numeric macro which can be defined in the makefile. Be aware that it uses C++17's constexpr if, so in case you find it useful make sure your compiler supports it.
constexpr int traitID = TRAIT_ID; // TRAIT_ID is a macro defined somewhere else.
template <typename T>
struct Wrapped // helper struct
{
using Type = T;
};
auto trait()
{
// Although it may look not that different from macros, the main difference
// is that here all the code below gets compiled.
if constexpr (traitID == 1)
return Wrapped<Trait1>{};
else if constexpr (traitID == 2)
return Wrapped<Trait2>{};
else if constexpr (traitID == 3)
return Wrapped<Trait3>{};
// add more cases if necessary
}
int main() // the contents of 'main' seems to have become more readable
{
using Trait = decltype(trait())::Type;
Runner<Trait> a;
return 0;
}
Also, here's a live example at Coliru.
Related
I am curious about whether it is possible to ensure at compile time that a method is called in exactly one place.
Note that it is OK if the function is called more than once (e.g. in a loop) - but it should not be called in two separate loops.
This can be broken into two parts, I am also interested in solutions that cover either part:
(a) ensure a method is called in at least one place
(b) ensure a method is called in at most one place
I have full control over the structure of the code, and different idioms that achieve the same idea are welcome.
// class.h
class MyClass {
public:
void my_method();
}
The following should not compile (never called)
#include "class.h"
int main() {
MyClass my_class;
}
The following should not compile (called in more than one place)
#include "class.h"
int main() {
MyClass my_class;
my_class.my_method();
while(true) {
my_class.my_method();
}
}
The following should compile (called in exactly one place):
#include "class.h"
int main() {
MyClass my_class;
while(true) {
my_class.my_method();
}
}
Low Tech Approach:
Since you have control over the code structure (which includes the build system, I assume), here is a low tech solution:
make the function name sufficiently unique
grep for the function name in your code. You are expecting it twice (assuming that you declaration and definition are colocated):
Once in the header
Once at the single call site
Alternatively:
If you really, really, really want to solve it with C++, then you could try
Use a compile time counter to figure out the number of uses within a compilation units
Make sure that the function would violate ODR if the header is included in multiple compilation units.
However, compile time counters are black magic (says I, and I really like TMP), and forcing ODR violations for this purpose seems like similar voodoo (at least you would require a test case that fails to link).
But seriously:
Don't do this. Whatever you do, it can be perverted with almost no effort by a wrapper function:
auto call_my_method(MyClass& o)
{
return o.my_method();
}
MyClass::my_method() is called only in the wrapper. Everybody else just calls the wrapper which is probably even inlined by the compiler.
As others suggested: It might be much more helpful if you would explain what you are trying to do.
Here's a rough idea that may work (too long for a comment - but incomplete for a good SO answer).
You may be able to achieve this by counting/checking template instantiations.
Templates are instantiated only upon use.
Similarly, template method/function bodies are not parsed nor compiled or linked (beyond ensuring valid syntax) if they are never called. This means that any instantiations within their bodies are not made).
You may be able to create a template that maintains some global instantiation count and static assert on that (or some other TMP mechanism to check past instantiations).
There is a partial solution to this question using the C preprocessor and GNU inline assembly:
Header file a.h:
struct A {
// Do not call this method directly, use the macro below to call it
int _method_vUcaJB5NKSD3upQ(int i, int j);
};
// Use inline assembly to ensure that this macro is used at most once
#define method_vUcaJB5NKSD3upQ(args...) \
_method_vUcaJB5NKSD3upQ(args); \
asm (".global once_vUcaJB5NKSD3upQ; once_vUcaJB5NKSD3upQ:");
Implementation file a.cc:
#include <iostream>
#include "a.h"
int A::_method_vUcaJB5NKSD3upQ(int i, int j) { return i+j+5; }
// Ensure that the macro is used at least once
extern "C" const char once_vUcaJB5NKSD3upQ;
static const char get_vUcaJB5NKSD3upQ = once_vUcaJB5NKSD3upQ;
int main() {
A a;
for(int i=0; i<7; i++) {
// Use a separate statement to call the method
// (terminated by a semicolon, it cannot be a sub-expression)
auto x = a.method_vUcaJB5NKSD3upQ(2, 3);
std::cout << x << std::endl;
}
return 0;
}
This solution is partial in the sense that it does not prevent the program to call the method beginning with the underscore directly without using the wrapper macro.
Use a constexpr counter. There is an implementation in another question
So I've been interested by the mersenne_twister engine and what it can do, so I decided to put the few lines of code required to initialize it inside my own class so that i simply have to create an instance of that class and can get any random numbers in any range i want without having to repeat those lines every time I need it.
I have suceeded so far but because I want my code to be as portble and efficient as possible I want to use the 64-bit engine depending on the architecture present.
I would like to avoid the way of using preprocessor macros defined by the compiler as that doesn't seem like the cleanest approach to me and would also require me to use the macros every time i mention the engine in my code.
My macro for the architecture l looks like this:
#define CPU_ARCH sizeof(nullptr)*8
And I declare the engine in the private space of the class so that i can init it in the constructor like this:
engine = mt19937(seed);
and use it in my random function like this:
double Random::giveRnd() {
return distribution(engine);
}
This looks fine right now but I have yet to find a way to implement both architectures with the same name "engine" in a way that the engine to be used is chosen at startup.
I have attempted the following:
Using a template to create a variable named engine that later gets
assigned either mt19337 or mt19337_64 which results in the compiler
complaining that
error: data member 'engine' cannot be a member template
with the following implementation:
class Random {
public:
[...]
private:
template<typename T>
T engine;
[...]
};
Using boost::variant which requires me to tell
my giveRnd() function which type to use when I use the engine which
is not possible since the type is not known at compile time
Not declaring the engine in the header file at all although this
results in the giveRnd() function not being able to use the engine
because it is not in the same scope.
Using preprocessor macros in the header file and then use typeid in
the source code to find out which engine was used, which doesn't seem
to be possible like this:
if(CPU_ARCH==32) { engine = mt19337(seed) }
because the compiler doesn't know that the engine will always be
32-bit in this case and complains that I cannot use the '=' operator
on two different types.
Does anyone have an idea on how to make this possible in a atleast somewhat clean way? Or do I need to fall back on the preprocessor macros?
You can implement behaviour that depends on CPU_BITS by making a class template that takes CPU_BITS as a template argument, and is specialized for expected values. For example:
#include <random>
template<size_t N> struct CpuOpts;
template<> struct CpuOpts<32> { using EngineType = std::mt19937; };
template<> struct CpuOpts<64> { using EngineType = std::mt19937_64; };
enum { CPU_BITS = sizeof(nullptr)*8 };
using CurrentCpuOpts = CpuOpts<CPU_BITS>;
struct Random
{
CurrentCpuOpts::EngineType engine;
};
int main()
{
Random r;
r.engine.seed(123456);
}
I started writing a simulation and decided to try use a more objected oriented approach. As such I also decided using a template parameter in the CUDA kernel, which indicates the spatial dimension of the simulation. The problem is, because of the restriction of implementing template functions in the header files, I had to use a complicated approach to keep make the kernel wrapper callable from .cpp source files.
My approach was to overload the wrapper function for 2 and 3 dimensions. I then have a class for wrapper class which deals with initialization and managing the kernel resources. Unfortunately, because of the restriction I mentioned, I have to keep two members for template classes, i.e.
struct kernelWrapper{
KernelWrapper(Simulation<2> *simulation):
d_(2),
simulation2d_(simulation)
{}
KernelWrapper(Simulation<3> *simulation):
d_(3),
simulation3d_(simulation)
{}
process(void){ //wrapper function for kernel launching
switch(d_){
case 2:
kernel<2><<<..., ...>>>(...);
break;
}
case 3:
kernel<3><<<..., ...>>>(...);
break;
}
default:
break;
}
int d_;
union{
Simulation<2> *simulation2d_;
Simulation<3> *simulation3d_;
};
union{
Lattice<2> *lattice2d_d;
Lattice<3> *lattice3d_d;
};
};
I was thus wondering if you know of a better way to achieve what I'm trying to do, that is, to make a wrapper for a template CUDA kernel.
UPDATE: I'd like to add one more solution I've found out after making the above post. As indicated by the C++ faq (points 13-15) one can put the template implementation in a source file and explicitly instantiate the templates that are needed, i.e. in my case for 2 and 3 dimensions. Using C++11, one can take this a step further and introduce the keyword extern in the template definition to save some compiling/linking time, also explained here.
The problem is, because of the restriction of implementing template
functions in the header files, I had to use a complicated approach to
keep make the kernel wrapper callable from .cpp source files.
It is legal to write a template declared code in .cpp
Whether kernelWrapper is in .hpp or .cpp you should have a code that looks like
template<int d_>
struct kernelWrapper
{
KernelWrapper(Simulation<d_> *simulation) : simulation_(simulation)
{}
process(void)
{
kernel<d_><<<..., ...>>>(...);
}
Simulation<d_>* simulation_;
Lattice<d_>* lattice2d_;
};
Also avoid using switch/case to select a kernel, use something like:
int const max_dimension = 4;
template<int static_dimension>
void select_kernel(int dynamic_dimension)
{
if(dynamic_dimension == static_dimension)
{
call_kernel<static_dimension>();
}
select_kernel<static_dimension+1>(dynamic_dimension);
}
template<>
void select_kernel<max_dimension>(int dynamic_dimension)
{
// error message
}
void select_kernel(int dynamic_dimension)
{
select_kernel<1>(dynamic_dimension);
}
If such selection is frequent, it makes sens to not using templates.
In our library we have a number of "plugins", which are implemented in their own cpp files. Each plugin defines a template function, and should instantiate this function over a whole bunch of types. The number of types can be quite large, 30-100 of them, and can change depending on some compile time options. Each instance really have to be compiled and optimized individually, the performance improves by 10-100 times. The question is what is the best way to instantiate all of these functions.
Each plugin is written by a scientist who does not really know C++, so the code inside each plugin must be hidden inside macros or some simple construct. I have a half-baked solution based on a "database" of instances:
template<int plugin_id, class T>
struct S
{
typedef T (*ftype)(T);
ftype fp;
};
// By default we don't have any instances
template<int plugin_id, class T> S::ftype S::fp = 0;
Now a user that wants to use a plugin can check the value of
S<SOME_PLUGIN,double>::fp
to see if there is a version of this plugin for the double type. The template instantiation of fp will generate a weak reference, so the linker will use the "real" instance if we define it in a plugin implementation file. Inside the implementation of SOME_PLUGIN we will have an instantiation
template<> S<SOME_PLUGIN,double>::ftype S<SOME_PLUGIN,double>::fp =
some_plugin_implementation;
This seems to work. The question is if there is some way to automatically repeat this last statement for all types of interest. The types can be stored in a template class or generated by a template loop. I would prefer something that can be hidden by a macro. Of course this can be solved by an external code generator, but it's hard to do this portably and it interfers with the build systems of the people that use the library. Putting all the plugins in header files solves the problem, but makes the compiler explode (needing many gigabytes of memory and a very long compilation time).
I've used http://www.boost.org/doc/libs/1_44_0/libs/preprocessor/doc/index.html for such magic, in particular SEQ_FOR_EACH.
You could use a type list from Boost.MPL and then create a class template that recursively eats that list and instantiates every type. This would however make them all nested structs of that class template.
Hmm, I don't think I understand your problem correctly, so apologies if this answer is way off the mark, but could you not have a static member of S, which has a static instance of ftype, and return a reference to that, this way, you don't need to explicitly have an instance defined in your implementation files... i.e.
template<int plugin_id, class T>
struct S
{
typedef T (*ftype)(T);
static ftype& instance()
{
static ftype _fp = T::create();
return _fp;
}
};
and instead of accessing S<SOME_PLUGIN,double>::fp, you'd do S<SOME_PLUGIN,double>::instance(). To instantiate, at some point you have to call S<>::instance(). Do you need this to happen automagically as well?
EDIT: just noticed that you have a copy constructor, for ftype, changed the above code.. now you have to define a factory method in T called create() to really create the instance.
EDIT: Okay, I can't think of a clean way of doing this automatically, i.e. I don't believe there is a way to (at compile time) build a list of types, and then instantiate. However you could do it using a mix... Hopefully the example below will give you some ideas...
#include <iostream>
#include <typeinfo>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/algorithm.hpp>
using namespace std;
// This simply calls the static instantiate function
struct instantiate
{
template <typename T>
void operator()(T const& x) const
{
T::instance();
}
};
// Shared header, presumably all plugin developers will use this header?
template<int plugin_id, class T>
struct S
{
typedef T (*ftype)(T);
static ftype& instance()
{
cout << "S: " << typeid(S<plugin_id, T>).name() << endl;
static ftype _fp; // = T::create();
return _fp;
}
};
// This is an additional struct, each plugin developer will have to implement
// one of these...
template <int plugin_id>
struct S_Types
{
// All they have to do is add the types that they will support to this vector
static void instance()
{
boost::fusion::vector<
S<plugin_id, double>,
S<plugin_id, int>,
S<plugin_id, char>
> supported_types;
boost::fusion::for_each(supported_types, instantiate());
}
};
// This is a global register, so once a plugin has been developed,
// add it to this list.
struct S_Register
{
S_Register()
{
// Add each plugin here, you'll only have to do this when a new plugin
// is created, unfortunately you have to do it manually, can't
// think of a way of adding a type at compile time...
boost::fusion::vector<
S_Types<0>,
S_Types<1>,
S_Types<2>
> plugins;
boost::fusion::for_each(plugins, instantiate());
}
};
int main(void)
{
// single instance of the register, defining this here, effectively
// triggers calls to instanc() of all the plugins and supported types...
S_Register reg;
return 0;
}
Basically uses a fusion vector to define all the possible instances that could exist. It will take a little bit of work from you and the developers, as I've outlined in the code... hopefully it'll give you an idea...
In my C++ header files I try to use forward declarations (class MyClass;) instead of #including the class header, as recommended in many C++ coding standards (the Google C++ Style Guide is one).
Unfortunately, when I introduce enumerations, I can't do the forward declaration any more. Like this:
//// myclass1.hpp ////
class MyClass1
{
enum MyEnum1
{
Enum_A, Enum_B, Enum_C
};
};
//// myclass2.hpp ////
// I want to avoid this
#include "myclass1.hpp"
// I'd prefer to do this (forward declaration)
class MyClass1;
class MyClass2
{
// This is o.k.: I only need to forward declare MyClass1
MyClass1* ptr;
// This forces me to #include, but I don't want to!
void func( MyClass1::MyEnum1 e );
};
The best solution I can think of so far is to replace enums with member constants:
//// myclass1.hpp ////
MyClass1
{
static const int Enum_A;
static const int Enum_B;
static const int Enum_C;
};
//// myclass1.cpp ////
const int Enum_A = 1;
const int Enum_B = 2;
const int Enum_C = 3;
In this case, though, the solution seems worse than the problem.
I'm currently looking through Large Scale C++ Software Design (Lakos) and Working Effectively with Legacy Code (Feathers) for dependency breaking techniques, but I haven't found a good solution yet.
This is difficult to do nicely. Perhaps moving enums to a common header file would be a reasonable solution?
Edit: I know the question asked to avoid including a header file, but there's just no way (AFAIK) to do this. Moving enums to a separate header file at least minimises the amount of stuff in the header file you do need to include. It's certainly better than the craziness suggested in the question!
You cannot forward declare enum values - and your workaround is a step down the path to complete madness.
Are you experiencing any major compilation slowdowns caused by #including headers? If not, just #include them. Use of forward declarations is not "best practice" it is a hack.
You can use forward declarations only when you are declaring a pointer. If you are declaring a non-pointer variable, you will have to include the relevant header file.
Since an enum variable is not a pointer you can't use forward declarations. And I don't think there's an alternative solution.
C++0x's strongly typed enums can be forward declared. GCC 4.4.0 and CodeGear C++Builder 2009 support strongly typed enums.
There are a few enum-like classes floating around like the (proposed but never finalized and accepted) Boost.Enum available for download from the Boost Vault at this link. Since Boost.Enums are classes, they can be forward declared.
However, just putting enums in a separate file (as in this answer) seems the simplest, best solution (barring C++0x suport).
You can use template arguments to program against 'general' enum types. Much like this:
// enum.h
struct MyClass1 { enum e { cE1, cE2, cELast }; };
// algo.h
// precondition: tEnum contains enumerate type e
template< typename tEnum > typename tEnum::e get_second() {
return static_cast<typename tEnum::e>(1);
}
// myclass1.h
// myclass.h
template< typename tClass1 >
class MyClass2
{
tClass1 * ptr;
void func( tClass1::e e );
};
// main.cpp
#include "enum.h"
#include "algo.h"
int main(){ return get_second<Enum>(); }
I don't think (I can be proven incorrect) that you can forward declare an internal type, nor an enumeration. You will need the definition of the enclosing class to use the enum.
While most style guides enforce not including unnecessary headers, in your case the header is necessary. Other options you can consider if you really want to avoid the inclusion would be defining the enumeration outside of the class and including the header that defines the enum.
Forward declaration of enumerations has actually been proposed by the C++ standards committee. See this paper (pdf). It would certainly be a good feature!
If you are really running into compilation slowdowns because of header inclusion, the other option is to use an int instead of an enum. This is a rather unpopular approach since it degrades type safety. If you do take this approach, then I would also recommend adding code to programmatically do the bounds checking:
// in class1.h
class Class1 {
public:
enum Blah {
kFirstBlah, // this is always first
eOne = kFirstBlah,
...
kLastBlah // this is always last
};
};
// in checks.h
#include <stdexcept>
namespace check {
template <typename T, typename U>
U bounds(U lower, T value, U upper) {
U castValue = static_cast<U>(value);
if (castValue < lower || castValue >= upper) {
throw std::domain_error("check::bounds");
}
return castValue;
}
} // end check namespace
// in class2.h
class Class2 {
public:
void func(int blah);
};
// in class2.cpp
#include "class2.h"
#include "class1.h"
#include "checks.h"
void Class2::func(int blah) {
Class1::Blah blah_;
blah_ = check::bounds(Class1::kFirstBlah, blah, Class1::kLastBlah);
}
It's not the prettiest solution, but it does solve the header dependency problem by moving some of the type safety that static compilation gives you into runtime code. I've use similar approaches in the past and found that a check namespace used in this way can make the resulting code almost as readable as enum based code with very little effort.
The caveat is that you do have to make an effort to write exception-safe code which I recommend regardless of whether you adopt this approach or not ;)