Hot to initialize static const member in specialized template code? - c++

I'm currently not able to set up my class members like I want to. My templated class is only specialized for sensible integer types (unsigned and “small”). Each specialization needs a rather big look-up table that only depends on the type. So I thought it should definitely be static (and const) and created only once.
As C++ doesn't have static constructors I learned that you can create a class that does the heavy stuff on initialization and have that as a static member.
I reduced my code to these basics:
// Of this, I only want one instance per type,
// because the table can get big.
template<class T>
struct LookUp
{
static int const SIZE = 1 << (sizeof(T) << 3);
std::vector<T> table;
LookUp()
: table{ SIZE }
{
for (int i = 0; i < SIZE; ++i)
{
// Dummy code
table[i] = i;
}
}
};
// "Normal" template class with common code for all types.
template<class T>
class LbpHelper
{
typedef /*...*/ image;
};
// No functionality for the general case.
template<class T>
class Lbp
{
};
// But for this (among others) we have something.
template<>
class Lbp<uint8_t> : public LbpHelper<uint8_t>
{
typedef uint8_t value_type;
typedef Lbp::image image;
static LookUp<value_type> _lookup; // <-- This is the mean one.
public:
// Stuff...
};
Initializing static members seems to confuse a lot of users, especially when it comes to templates and specialization. I read quite some answers here but none of them solved my problem.
I tried having something like
// The type of the class is the same as the type of the member class.
template<> LookUp<uint8_t> Lbp<uint8_t>::_lookup{};
template<> LookUp<uint16_t> Lbp<uint16_t>::_lookup{};
in the header or the source file or both. I tried with or without a class T in the angle brackets (and using T to the right of course), leaving out the template<> alltogether, having the {}s only in the source — I don't know what else. Nothing worked.
Visual C++ either tells me that _lookup is not a member or that it is not an entity that can be specialized or this: error C2373: '_lookup' : redefinition; different type modifiers.
Can someone please tell me what to put where so that it compiles?

Just drop the template<> bit, and put the definition of the static data members in a .cpp file:
LookUp<uint8_t> Lbp<uint8_t>::_lookup{};
LookUp<uint16_t> Lbp<uint16_t>::_lookup{};
[Live example]
... and, since the type of _lookup is a class, you can leave out the {} as well; its default constructor will be called anyway. This might please VC++ if you're using a version which does not support uniform initialisation.
Why this is the proper way: template<> is used to introduce explicit specialisations. You're not introducing an explicit specialisation - you're defining a data member of an already defined explicit specialisation.
This is covered by C++11 14.7.3/5:
... Members of an explicitly specialized class template are
defined in the same manner as members of normal classes, and not using the template<> syntax. The same
is true when defining a member of an explicitly specialized member class. ...

Related

CRTP - visibility of the type of a nested leaf class

I would like to understand if it is possible to use a nested class of a leaf CRTP class in the base CRTP class. The example below demonstrates the problem.
#include <iostream>
using namespace std;
template<class T>
class A
{
protected:
T* asLeaf(void)
{return static_cast<T*>(this);}
T const* asLeaf(void) const
{return static_cast<T const*>(this);}
public:
struct Inner
{int a = 10;};
void dispInner(void) const
{std::cout << asLeaf()->inner.a << std::endl;}
// I would like to use T::Inner in this class, e.g.
// typename T::Inner mvInnerA;
// However, I understand that it is not possible to
// use it in the form that is stated above. Thus,
// I am looking for any possible workarounds.
};
class B: public A<B>
{
public:
struct Inner: public A<B>::Inner
{int b = 20;};
protected:
friend A<B>;
B::Inner inner;
public:
void dispInner(void) const
{
A<B>::dispInner();
std::cout << asLeaf()->inner.b << std::endl;
}
};
int main()
{
B b;
b.dispInner();
return 0;
}
EDIT
I would like to provide several further comments based on the feedback that I have received:
I am aware that I may not be using adequate design practices. In particular, it may be questioned whether A should be aware of the existence of inner. However, I would like to define an object inner of the type B::Inner in A instead of providing the definition of inner in B and using it in A.
I am aware that I cannot forward declare B and/or B::Inner and of the reasons why this cannot be done. Thus, technically, the design problem does not have a solution. However, I am looking for a feasible workaround.
I have already considered several alternative solutions:
One of the possible feasible solutions is not to make attempts to 'define' B::Inner inner in A and use the member functions of A to provide the functionality that allows to modify the A<B>::Inner part of B::Inner inner.
Another possible solution is to define the classes A<B>::Inner and B::Inner explicitly (i.e. not as nested classes). However, I would prefer to avoid this, because, by design, it is not expected that any classes that do not derive from A will need to interact with A<B>::Inner or the classes that derive from A<B>::Inner
Both solutions that I have presented may be acceptable. However, I am looking for any feasible alternatives.
The standard say that:
A class is considered a completely-defined object type (or complete type) at the closing } of the class-specifier.
It follows that B isn't a completely-defined object when you specialize A as A<B>. Therefore you can't expect to be able to access its members or types or whatever from within the definition of A (even though you can call back the derived class from within the definition of a member method of A, that is perfectly legal instead other than the purpose of the CRTP idiom).
In other terms, when you do this:
typename T::Inner mvInnerA
You have no guarantees that T is a completely-defined object and that's why you get the error.
A few alternatives:
You can define mvInnerType as a function instead of as a type and use it as a factory to create objects of type T::inner:
[static] auto mvInnerA() {
return typename T::Inner{};
}
Use it either as:
auto foo = A<B>::mvInnerA();
Or:
auto foo = obj.mvInnerA();
The right form depends on the fact that you make it static or not.
Note that you can still use the hidden type somehow, even if its name isn't accessible:
using HiddenType = decltype(A<B>::mvInnerA());
HiddenType foo = A<B>::mvInnerA();
You can define mvInnerA using a template a alias declaration like this:
template<typename U = T>
using mvInnerA = typename U::Inner;
Then use it as:
auto foo = A<B>::mvInnerA<>{};
For the type T is (let me say) indirectly used through U only when mvInnerA is instantiated, you don't have the problem mentioned above. The price to pay for that is the presence of an annoying <> and the fact that one can pass a custom type to mvInnerA.
How you can use an inner type of a CRTP template parameter is severely limited.
There can be no use in the scope of the class template definition itself. When instantiating the template, it will require the type B to be fully defined, which like skypjack points out, it isn't. You can however use it in contexts that aren't immediately instantiated with the class template, which is mostly the member functions of A.
And while you cannot have a type alias for B::Inner, you can have a type alias template
template<class C>
using Inner = typename C::Inner
Which A's member functions can use to avoid the verbosity of typename B::Inner and instead use Inner<B>.

Can I have a std::vector of template function pointers?

I have a template function that I want to store a pointer to inside a std::vector.
The function looks like this:
template<typename T> void funcName(T& aT, std::vector<std::string>& fileName){...}
Now I want to store multiple pointers to functions of this kind inside a std::vector. For non-template functions I would do it like this:
typedef std::vector<std::string> string_vt;
typedef void func_t(T&, string_vt&);
typedef func_t* funcPointer;
typedef std::vector<funcPointer> funcPointer_vt;
But what is the correct syntax for template functions? How can I store them?
EDIT: First of all, thank you for your fast response. This was my first Question on Stack Overflow, so I am sorry for not providing enough information.
The set of T is finite, it can either be of type ClassA or type classB. In these function templates I want to do changes to T (so either ClassA or ClassB) with some hard coded data. I have 8 of these functions, which basically initiate a default constructed T with data specific to the function. In my program, I want to initiate 2*8 default constructed T's (8 ClassA and 8 ClassB). Therefore I run a for loop, calling one function after the other, to initiate my T objects with the function's body data.
for(int i = 0; i < initT.size(); ++i){
init_T[i]<T>(someT, fileName);
}
The for loop has as much iterations as there are function pointers inside the vector. At every iteration the function is called with some previously default constructed T and some other parameter. At the end the goal is to have 8 initiated T's with data specific to the function.
EDIT2: In case it helps, here is some actual source code. Inside the following function template I want to access my vector of function pointers in order to call the respective function.
template<typename T_Relation, typename T_Relation_Vec, bool row>
void bulk_load(initRelation_vt& aInitFunctions, T_Relation_Vec& aRel_Vec, const bool aMeasure, const uint aRuns, const char* aPath)
{
for(size_t i = 0; i < aRuns; ++i)
{
MemoryManager::freeAll();
aRel_Vec.clear();
string_vt fileNames;
for(size_t j = 0; j < aInitFunctions.size(); ++j)
{
aRel_Vec.emplace_back(T_Relation());
aInitFunctions[j]<T_Relation>(aRel_Vec[j], fileNames);
BulkLoader bl(fileNames[j].c_str(), tuples, aRel_Vec[j], delimiter, seperator);
Measure lMeasure;
if(aMeasure)
{
lMeasure.start();
}
try
{
bl.bulk_load();
if(row)
{
BulkInsertSP bi;
bi.bulk_insert(bl, aRel_Vec[j]);
}
else
{
BulkInsertPAX bi;
bi.bulk_insert(bl, aRel_Vec[j]);
}
}
catch(std::exception& ex)
{
std::cerr << "ERROR: " << ex.what() << std::endl;
}
lMeasure.stop();
if(aMeasure)
{
std::ofstream file;
file.open (aPath, std::ios::out | std::ios::app);
//print_result(file, flag, lMeasure.mTotalTime());
file.close();
}
}
}
}
This line is where the vector of function template pointers is accessed.
aInitFunctions[j]<T_Relation>(aRel_Vec[j], fileNames);
Templates are an advanced technique for static polymorphism. In a typed language, like C++, without static polymorphism you would have to separately define every entity used and precisely indicate every entity referred to.
Mechanisms of static polymorphism in C++ allow to automate indication of function or method and defer it until build via overloading. It allows you to define multiple entities sharing some characteristics at once via templates and defer definition of particular specializations until build, inferred from use.
(Notice that in various scenarios, static polymorphism allows separate code, so that changes to use and to definition are independent, which is very useful.)
The important implication of this mechanism is that every specialization of your template may be of different type. It is unclear, as of when I'm responding, whether you want to store pointers to a single or multiple types of specialization in one type of container. The possibilities depend also on parameter and result types of the function template.
A function in C++ has a type that is a combination of list of its parameter types and its return type. In other words, two functions that take and return the same types are of the same type. If your function template neither took or returned template parameter type (ie. T) nor templated type (eg. std::vector<T>), every specialization of this function template would be taking and returning the same types and would therefore be a function of the same type.
template <typename T>
int func() { ... }
This (arguably useless) function template takes no arguments and returns int, whatever T is used to specialize the template. Therefore a pointer to it could be used wherever the parameter is defined as int (*f)(). In this case you could keep pointer to any specialization in one vector.
typedef std::vector<std::string> string_vt;
typedef int func_t();
typedef func_t* funcPointer;
typedef std::vector<funcPointer> funcPointer_vt;
funcPointer x = &func<int>;
funcPointer y = &func<float>;
As can be seen, every specialization of your function template is of the same type and both pointers fit in the same container.
Next case - what if function header depends on a template parameter? Every specialization would have a different signature, that is a different function type. The pointers to all of them would be of different types - so it wouldn't be possible to even typedef this pointer once.
template <typename T>
void func(std::vector<T> param) { ... }
In this case function template specialization is of different type depending on T used to specialize.
typedef int func_t_int(std::vector<int>);
typedef func_t_int* funcPointerInt;
typedef std::vector<funcPointerInt> funcPointerInt_vt;
typedef float func_t_float(std::vector<float>);
typedef func_t_float* funcPointerFloat;
typedef std::vector<funcPointerFloat> funcPointerFloat_vt;
funcPointerInt x = &func<int>;
funcPointerFloat x = &func<float>;
Specializations are of different types, because they take different type of vectors. Pointers do not fit in the same container.
It's mention-worthy at this point, that in this case it's not necessary to define every pointer type separately. They could be a template type:
template <typename T>
using funcPointer = void (*)(std::vector<T>);
Which now allows funcPointer<int> to be used as a type qualifier, in place of earlier funcPointerInt.
funcPointer<float> y = &func<float>;
In more complicated situations a template could be created, whose every specialization is of a different type, and then would use a single instance of concrete vector to store various pointers to functions of type of only one of the specializations of your template. Although a simple template like in the example can only produce a single function per type, because every specialization yields one type of function and one function of that type, it's not impossible to conceive a scenario where various pointers to functions are obtained, both to specializations and usual functions, perhaps from various sources. So the technique could be useful.
But yet another scenario is that despite every specialization of the template being of different type, there's a need to store pointers to various specializations in single std::vector. In this case dynamic polymorphism will be helpful. To store values of different types, fe. pointers to functions of different types, in one type of variable, requires inheritance. It is possible to store any subclass in a field defined as superclass. Note however, that this is unlikely to accomplish anything really and probably not what you're really looking for.
I see two general possibilities now. Either use a class template with a method, which inherits from a non-template class.
template <typename T>
class MyClass : BaseClass
{
public:
T operator()(const T& param, int value);
}
MyClass<int> a;
MyClass<float> b;
BaseClass* ptr = &a;
ptr = &b;
While every specialization of this class may be of a different type, they all share superclass BaseClass, so a pointer to a BaseClass can actually point to any of them, and a std::vector<funcPointerBase> can be used to store them. By overloading operator() we have create an object that mimics a function. The interesting property of such a class is that it can have multiple instances created with parameter constructors. So effectively class template produces specializations of multiple types, and in turn every specialized class can produce instances of varying parametrization.
template <typename T>
class MyClass : BaseClass
{
int functor_param;
public:
MyClass(int functor_param);
T operator()(const T& param, int value);
}
This version allows creation of instances that work differently:
MyClass<int> a(1);
MyClass<int> b(2);
MyClass<float> c(4);
MyClass<int>* ptr = &a;
ptr = &b;
ptr = &c;
I am no expert on functors, just wanted to present the general idea. If it seems interesting, I suggest researching it now.
But technically we're not storing function pointers, just regular object pointers. Well, as stated before, we need inheritance to use one type of variable to store values of various types. So if we're not using inheritance to exchange our procedural functions for something dynamically polymorphic, we must do the same to pointers.
template <typename T>
T func(std::pair < T, char>) {}
template <typename T>
using funcPointer = T(*)(std::pair<T, char>);
template <typename T>
class MyPointer : BasePointer
{
funcPointer<T> ptr;
public:
MyPointer(funcPointer<T> ptr);
T()(std::pair <T, char>) operator*(std::pair <T, char> pair)
{
*ptr(pair);
}
};
This, again, allows creation of single std::vector<BasePointer> to store all possible pseudo-function-pointers.
Now the very important bit. How would You go about calling those, in either scenario? Since in both cases they are stored in a single std::vector<>, they are treated as if they were of the base type. A specific function call needs parameters of specific type and returns a specific type. If there was anything that all subclasses can do in the same way, it could be exposed by defining such a method in base class (in either scenario using functors or pointer..ors?), but a specific specialized function call is not that kind of thing. Every function call that You would want to perform in the end, after all this struggle, would be of a different type, requiring different type of parameters and/or returning different type of value. So they could never all fit into the same place in usual, not templated code, the same circumstances in execution. If they did, then dynamic polymorphism wouldn't be necessary to solve this problem in the first place.
One thing that could be done - which is greatly discouraged and probably defeats the purpose of dynamic polymorphism - is to detect subclass type at runtime and proceed accordingly. Research that, if you're convinced you have a good case for using this. Most likely though, it's probably a big anti-pattern.
But technically, anything you may want to do is possible somehow.
If I have correctly understood you, I may have a really simple and efficient solution:
template<class...Ts>
struct functor{
//something like a dynamic vtable
std::tuple<void(*)(Ts&,std::vector<std::string>&)...> instantiated_func_ptr;
template<class T>
void operator ()(T& aT,std::vector<std::string>& fileName){
get<void(*)(T&,std::vector<std::string>&)>(instantiated_func_ptr)
(aT,fileName);
}
};
Voilà!!
Until c++17, get<typename> is not defined so we have to define it (before the definition of the template functor above):
template<class T,class...Ts>
struct find_type{
//always fail if instantiated
static_assert(sizeof...(Ts)==0,"type not found");
};
template<class T,class U,class...Ts>
struct find_type<T,U,Ts...>:std::integral_constant<size_t,
find_type<T,Ts...>::value+1>{};
template<class T,class...Ts>
struct find_type<T,T,Ts...>:std::integral_constant<size_t,0>{};
template<class T,class...Ts>
constexpr decltype(auto) get(const std::tuple<Ts...>& t){
return get<find_type<T,Ts...>::value>(t);
}
And an example to show how to use it:
struct A{
void show() const{
std::cout << "A" << "\n";
}
};
struct B{
void show() const{
std::cout << "B" << "\n";
}
};
template<class T>
void func1(T& aT,std::vector<std::string>& fileName){
std::cout << "func1: ";
aT.show();
}
template<class T>
void func2(T& aT,std::vector<std::string>& fileName){
std::cout << "func2: ";
aT.show();
}
template<class T>
void func3(T& aT,std::vector<std::string>& fileName){
std::cout << "func3: ";
aT.show();
}
using functorAB = functor<A,B>;
int main(){
auto functor1=functorAB{{func1,func1}};//equivalent to functorAB{{func1<A>,func1<B>}}
auto functor2=functorAB{{func2,func2}};
auto functor3=functorAB{{func3,func3}};
auto v=std::vector<functorAB>{functor1,functor2,functor3};
auto a=A{};
auto b=B{};
auto fileNames = std::vector<std::string>{"file1","file2"};
for(auto& tf:v)
tf(a,fileNames);
for(auto& tf:v)
tf(b,fileNames);
}
In practice it is just a reproduction of the virtual call mechanism,
the tuple in functor is kind of virtual table. This code is not
more efficient than if you had written an abstract functor with virtual
operator() for each of your class A and B and then implemented it for each of
your functions... but it is much more concise, easier to maintain and may produce less binary code.

How to create concrete class from a template class

Say I have a template class:
template <typename T> class StringDeque:
public std::deque<T>
{
public:
...
private:
typedef std::deque<T> BaseClass;
};
Say I want to create concrete class ArrayString where T=std::string.
What is the proper way to achieve that:
define
#define ArrayString StringDeque<string>
typedef
typedef StringDeque < string > ArrayString;
inheritance
class ArrayString :
public StringDeque < string > {};
I'm not sure whether all of the suggestions are valid. Anyway I'm trying to figure out which practice most fits.
You want to give a name to a particular type (which happens to be an instantiation of a template). The C++ way to give names (aliases) to types is with a typedef:
typedef StringDeque<string> ArrayString;
Or, since C++11, with an alias declaration:
using ArrayString = StringDeque<string>;
Side note: when thinking about this stuff, it generally helps to think in terms of the correct template terminology. You don't have a "template class" (a class with special properties), you have a "class template" (a template for creating classes). The template is not a type; its instantiations are.
Proper ways:
typedef std::deque<std::string> StringDeque;
using StringDeque = std::deque<string>;
That said, here are some more notes on your question:
You wrote:
template <typename T> class StringDeque: public std::deque<T> // ...
std container classes are not meant as base classes. This means they should not be inherited from (and inheriting from them is UB).
When you want to use std container functionality in another class, the answer should always be encapsulation. That means, the correct way to build on the functionality of std::queue in your classes is:
template<typename T> class StringDequeue {
std::deque<T> storage;
public:
// add interface here that uses storage
};
You also proposed this:
#define ArrayString StringDeque<string>
Please never use define to declare a type. It works, but it has it's own pitfalls and is considered bad practice in C++.
Create type aliases with typedef or (since C++11) using:
typedef StringDeque<std::string> ArrayString;
using ArrayString = StringDeque<std::string>;
The preprocessor is a sledgehammer: occasionally useful but, with no knowledge of language-level constructs, prone to break code in surprising ways. In this case, I think the only problem is that the name won't be constrained to any scope; but that's reason enough to avoid it.
Inheritance creates a new type; while it's usually usable where the base type is, it's not completely interchangable, and doesn't inherit any constructors from the base type. So that's also not what you want for a simple type alias.

Call function of template class created at runtime

I have a tricky question about C++(11) template classes and their instantiation with types determined at runtime:
Following scenario:
The user defines the type of a template class using a config file (ROS parameters). This determines only the type of the template class, not the further logic:
Class definition:
template<typename T>
class MyClass {
//[...]
}
Exemplary code:
/* [Read parameter and write result to bool use_int] */
std::unique_ptr<MyClass> myclassptr {nullptr};
if(use_int) {
myclassptr.reset(MyClass<int>);
} else {
myclassptr.reset(MyClass<double>);
}
myclassptr->foobar();
/* [more code making use of myclassptr] */
So this code is (of course) not compiling, because the unique_ptr template must be specified also with the template type. However, then the problem arises that the template type must be the same for all objects assigned using reset.
One ugly solution would be to copy the code myclassptr->foobar(); and the following into each branch of if/else, which I really don't like.
I would like to see a solution similar to this:
/* [Read parameter and write result to bool use_int] */
MyClass<use_int ? int : double> myclass;
myclass.foobar();
What I have read so far is that something like this is also not possible.
Does anybody have a nice solution for this?
The simplest way to do this is:
class IClass{
virtual ~IClass {}
virtual void foobar()=0;
};
template<typename T>
class MyClass:public IClass {
public:
void foobar() override {
// code here
}
};
std::unique_ptr<IClass> myclassptr {};
if(use_int) {
myclassptr.reset(new MyClass<int>());
} else {
myclassptr.reset(new MyClass<double>());
}
myclassptr->foobar();
boost::variant would be another solution, but is usually used for unrelated types. Type erasure could be done, but again that is usually done when you have unrelated types you want to impose a uniform interface on.
In other languages generics look sort of like templates, but are actually an abstract interface with auto-generated typecasting and some typechecking added. C++ templates are function or class compile time factories. Two outputs of such factories are unrelated at runtime by default, and you can add such relations if you want.
Depending on what you want, you can make MyClass a variant type that holds either an int or a double, or you could use type erasure to hide the implementation behind an interface. The Boost.Variant library can help to implement the former.

Does a template instantiation in typedef have limited scope?

The template is similar to what the STL contains:
template <class T, int MAXSIZE>
class MyClass {
public:
class iterator : public std::iterator<std::input_iterator_tag,T> {
};
// constructors, destructor, methods...
};
The client's .h-file defines a typedef and methods returning the iterator:
class MyClassUser {
public:
typedef util::MyClass<eec::Packet*,20> PacketList;
//...
PacketList::iterator begin();
PacketList::iterator end();
};
The client's .h-file contains the definition of method begin:
PacketList::iterator MyClassUser::begin(){ ... } // flagged by the compiler
MyClassUser::PacketList::iterator MyClassUser::end(){ ... } // OK - according to answer
But this is flagged as ‘PacketList’ has not been declared although the .h file is most certainly included. Why?
Usage of PacketList::iterator is possible inside another method of MyClass. Also, there is no problem if I repeat the full instantiation:
util::MyClass<eec::Packet*,20>::iterator MyClassUser::begin(){ ... }
An acceptable solution should restrict the use of the "magic number" 20 to a single location. How is this possible?
Yes, typedef inside class are local to the class. Therefore you should write:
MyClassUser::PacketList::iterator MyClassUser::begin(){ ... }
Note 1: this has nothing to do with template.
Note 2: After MyClassUser::begin( the compiler knows that you are writing a method of MyClassUsuer and add MyClassUser to the local scopes that are searched for symbols. Therefore you don't need to write MyClassUser:: anymore.