Template specialization using typedefs - c++

While learning Vulkan I came across some code in the VulkanCookbook. in the VulkanCookbook the author writes the code to import the Vulkan functions and classes by hand. Well I've been slowly converting it over to the LunarG's SDK for Vulkan and I came across a problem in the under 64bit VkFence it typedef'd to VkFence_T* which is fine and all but in 32bit it's typedef'd as uint64_t which causes a problem for VkDestroyer which uses code similar to below
#include <iostream>
#include <stdint.h>
typedef uint64_t A;
typedef uint64_t B;
template<typename T>
class Handler
{
void DestroyObject( T parent );
};
template<>
inline void Handler<A>::DestroyObject(A object) {
std::cout << "destroy type A" << std::endl;
}
template<>
inline void Handler<B>::DestroyObject(B object) {
std::cout << "destroy type B!" << std::endl;
}
int main()
{}
is there any good way to handle this problem or do I have to go and rework all the example code to delete Objects by hand? I would like to compile under 32bit if possible.
Sorry if this question has been asked somewhere else I couldn't find it as google always came partial templating and other non-related topics. And I do understand the problem with the code the compiler is looking at _A and _B and just treating it a uint64_t without caring that they are named differently, which causes the DestroyObject overloads to be for the same template type causing the redefinition error.
Edit: fixed the code using invalid naming as that wasn't actually a core problem.

C++ doesn't have strong typedefs. A type alias is simply another name for an existing type, and is entirely equivalent to the type it aliases, when used.
You need A and B to be actual types, not aliases, which are both in a relationship with uint64_t. So long as you constrain yourself to integral types, you can construct new distinct ones out of them.
The solution is an enumeration with an underlying type specified for it.
#include <type_traits>
template<typename E>
using argument_t = std::conditional_t<std::is_enum<E>::value,
std::underlying_type_t<E>,
E>;
template<typename T>
class Handler
{
void DestroyObject( argument_t<T> parent );
};
enum A : uint64_t {};
enum B : uint64_t {};
template<>
inline void Handler<A>::DestroyObject(uint64_t object) {
std::cout << "destroy type A" << std::endl;
}
template<>
inline void Handler<B>::DestroyObject(uint64_t object) {
std::cout << "destroy type B!" << std::endl;
}
The above works like this:
The argument_t utility checks if E is an enumeration, and gives the underlying type for it. Otherwise it falls back to E itself.
The primary template accepts a T, and transforms the argument if needed.
Since A and B are distinct types now, you can specialize on each. The function accepts the underlying type as a parameter.

You almost have it right... What the above functions Handler<_A>::DestroyObject(_A object) and Handler<_B>::DestroyObject(_B object) actually are is concrete instantiations of a templated member function. Because the author did not provide a generic version of this function, you are having the issues you are with trying to instantiate the class with a uint32_t. The simple fix would be to write a template<> void Handler<uint32_t>::DestroyObject(uint32_t o) function. Without more context, I cannot offer better advice.

There is no way for a template to distinguish between being pasded A and B as a type parameter.
There may be alternatives to manually cleaning up objects, but your question is too vague and focused on finding a way to get a non-viable solition working to determine what your problem really is.
Probably you have to disntinguish between the types using something different than the types themselves.

Related

Where do normal templates end and meta templates begin?

Jörg's answer to this question nicely delineates between "normal" templates (what the question refers to, perhaps erroneously, as generics) which operate on data and meta templates which operate on a program. Jörg then wisely mentions that programs are data so its really all one and the same. That said, meta-templates are still a different beast. Where do normal templates end and meta templates begin?
The best test I can come up with is if a template's arguments are exclusively class or typename the template is "normal" and meta otherwise. Is this test correct?
The boundary: Signature with Logical Behaviour
Well, in my opinion the boundary-line is to be drawn where a template's signature stops to be a simple signature yielding runtime-code and becomes a definition of explicit or implicit logic, which will be executed/resolved at compile-time.
Some examples and explanation
Regular Templates, i.e. with only typename, class or possibly value-type template parameters, produce executable cpp code, once instantiated during compile time.
The code is (important) not executed at compile time
E.g. (very simple and most likely unrealistic example, but explains the concept):
template<typename T>
T add(const T& lhs, const T& rhs) {
return(lhs + rhs);
}
template<>
std::string add<std::string>(
const std::string& lhs,
const std::string& rhs) {
return (lhs.append(rhs));
}
int main() {
double result = add(1.0, 2.0); // 3.0
std::string s = add("This is ", " the template specialization...");
}
Once compiled, the root-template will be used to instantiate the above code for the type double, but will not execute it.
In addition, the specialization-template will be instantiated for the text-concatenation, but also: not executed at compile time.
This example, however:
#include <iostream>
#include <string>
#include <type_traits>
class INPCWithVoice {
void doSpeak() { ; }
};
class DefaultNPCWithVoice
: public INPCWithVoice {
public:
inline std::string doSpeak() {
return "I'm so default, it hurts... But at least I can speak...";
}
};
class SpecialSnowflake
: public INPCWithVoice {
public:
inline std::string doSpeak() {
return "WEEEEEEEEEEEH~";
}
};
class DefaultNPCWithoutVoice {
public:
inline std::string doSpeak() {
return "[...]";
}
};
template <typename TNPC>
static inline void speak(
typename std::enable_if<std::is_base_of<INPCWithVoice, TNPC>::value, TNPC>::type& npc)
{
std::cout << npc.doSpeak() << std::endl;
};
int main()
{
DefaultNPCWithVoice npc0 = DefaultNPCWithVoice();
SpecialSnowflake npc1 = SpecialSnowflake();
DefaultNPCWithoutVoice npc2 = DefaultNPCWithoutVoice();
speak<DefaultNPCWithVoice>(npc0);
speak<SpecialSnowflake>(npc1);
// speak<DefaultNPCWithoutVoice>(npc2); // Won't compile, since DefaultNPCWithoutVoice does not derive from INPCWithVoice
}
This sample shows template meta programming (and in fact a simple sample...).
What happens here, is that the 'speak'-function has a templated parameter, which is resolved at compile time and decays to TNPC, if the type passed for it is derived from INPCWithVoice.
This in turn means, if it doesn't, the template will not have a candidate for instantiation and the compilation already fails.
Look up SFINAE for this technique: http://eli.thegreenplace.net/2014/sfinae-and-enable_if/
At this point there's some logic executed at compile time and the entire program, will be fully resolved once linked to the executable/library
Another very good example is: https://akrzemi1.wordpress.com/2012/03/19/meta-functions-in-c11/
Here you can see a template meta programming implementation of the factorial-function, demonstrating, that even the bytecode can be entirely equal to a fixed-value use, if the meta-template decays to a constant.
Finalizing example: Fibonacci
#include <iostream>
#include <string>
#include <type_traits>
template <intmax_t N>
static unsigned int fibonacci() {
return fibonacci<N - 1>() + fibonacci<N - 2>();
}
template <>
unsigned int fibonacci<1>() {
return 1;
}
template <>
unsigned int fibonacci<2>() {
return fibonacci<1>();
}
template <intmax_t MAX>
static void Loop() {
std::cout << "Fibonacci at " << MAX << ": " << fibonacci<MAX>() << std::endl;
Loop<MAX - 1>();
}
template <>
void Loop<0>() {
std::cout << "End" << std::endl;
}
int main()
{
Loop<10>();
}
This code implements scalar template argument only template meta programming for the fibonacci-sequence at position N.
In addition, it shows a compile-time for loop counting from 10 to 0!
Finally
I hope this clarifies things a bit.
Remember though: The loop and fibonacci examples instantiate the above templates for each index!!!
Consequently, there's a horrible amount of redundancy and binary bloat!!!
I'm not the expert myself and I'm sure there's a template meta programming kung fu master on stackoverflow, who can append any necessary information missing.
Attempt to differentiate and define the terms
Let's first try to roughly define the terms. I start with a hopefully good enough definition of "programming", and then repeatedly apply the "usual" meaning of meta- to it:
programming
Programming results in a program that transforms some data.
int add(int value) { return value + 42; }
I just wrote code that will result in a program which transforms some data - an integer - to some other data.
templates (meta programming)
Meta programming results in a "program" that transforms some program into another. With C++ templates, there's no tangible "program", it's an implicit part of the compiler's doings.
template<typename T>
std::pair<T,T> two_of_them(T thing) {
return std::make_pair(thing, thing);
}
I just wrote code to instruct the compiler to behave like a program that emits (code for) another program.
meta templates (meta meta programming?)
Writing a meta template results in a ""program"" that results in a "program" which results in a program. Thus, in C++, writing code that results in new templates. (From another answer of me:)
// map :: ([T] -> T) -> (T -> T) -> ([T] -> T)
// "List" "Mapping" result "type" (also a "List")
// --------------------------------------------------------
template<template<typename...> class List,
template<typename> class Mapping>
struct map {
template<typename... Elements>
using type = List<typename Mapping<Elements>::type...>;
};
That's a description of how the compiler can transform two given templates into a new template.
Possible objection
Looking at the other answers, one could argue that my example of meta programming is not "real" meta programming but rather "generic programming" because it does not implement any logic at the "meta" level. But then, can the example given for programming be considered "real" programming? It does not implement any logic either, it's a simple mapping from data to data, just as the meta programming example implements a simple mapping from code (auto p = two_of_them(42);) to code (the template "filled" with the correct type).
Thus, IMO, adding conditionals (via specialization for example) just makes a template more complex, but does not change it's nature.
Your test
Definitively no. Consider:
template<typename X>
struct foo {
template<typename Y>
using type = X;
};
foo is a template with a single typename parameter, but "results" in a template (named foo::type ... just for consistency) that "results" - no matter what parameter is given - to the type given to foo (and thus to the behavior, the program implemented by that type).
Let me start answering using a definition from dictionary.com
Definition
meta -
a prefix added to the name of a subject and designating another subject that analyzes the original one but at a more abstract, higher level: metaphilosophy; metalinguistics.
a prefix added to the name of something that consciously references or comments upon its own subject or features: a meta-painting of an
artist painting a canvas.
Template programming is formost used as a way to express relations in the type system of C++. I would argue it is therefore fair to say that template programming inherently makes use of the type system itself.
From this angle of perspective, we can rather directly apply the definition given above. The difference between template programming and meta (template-)programming lies the treatment of template arguments and the intended result.
Template code that inspects its arguments clearly falls into the former defintion while the creation of new types from template arguments arguably falls into the later. Note that this must also be combined with the intent of your code to operate on types.
Examples
Let's take a look at some examples:
Implementation of std::aligned_storage;
template<std::size_t Len, std::size_t Align /* default alignment not implemented */>
struct aligned_storage {
typedef struct {
alignas(Align) unsigned char data[Len];
} type;
};
This code fulfills the second condition, the type std::aligned_storage is used to create another type. We could make this ever clearer by creating a wrapper
template<typename T>
using storage_of = std::aligned_storage<sizeof(T), alignof(T)>::type;
Now we fulfill both of the above, we inspect the argument type T, to extract its size and aligment, then we use that information to construct a new type dependent on our argument. This clearly constitutes meta-programming.
The original std::aligned_storage is less clear but still quite pervasive. We provide a result in the form of a type, and both of the arguments are used to create a new type. The inspection arguably happens when the internal array type of type::data is create.
A counter examples for completeness of the argument:
template<
class T,
class Container = std::vector<T>,
class Compare = std::less<typename Container::value_type>
> class priority_queue { /*Implementation defined implementation*/ };
Here, you might have the question:
But doesn't priority queue also do type inspection, for example to retrieve the underlying Container, or to assess the type of its iterators?
And yes it does, but the goal is different. The type std::priority_queue itself does not constitute meta template programming, since it doesn't make use of the information to operate within the type system. Meanwhile the following would be meta template programming:
template<typename C>
using PriorityQueue = std::priority_queue<C>;
The intent here is to provide a type, not the operations on the data themselves. This gets clearer when we look at the changes we can make to each code.
We can change the implementation of std::priority_queue maybe to change the permitted operations. For example to support a faster access, additional operations or compact storage of the bits inside the container. But all of that is entirely for the actual runtime-functionality and not concerned with the type system.
In contrast look at what we can do to PriotityQueue. If we were to choose a different underlying implementation, for example if we found that we like Boost.Heap better or that we link against Qt anyways and want to choose their implementation, that's a single line change. This is what meta programming for, we make choices within the type system based arguments formed by other types.
(Meta-)Template signatures
Regarding your test, as we have seen above, storage_of has exclusively typename arguments but is very clearly meta programming. If you dig deaper, you will find that the type system itself is, with templates, Turing-complete. Without even needing to explicitely state any integral variables, we could for example easily replace them by recursively stacked templates (i.e. Zermelo construction of the natural numbers)
using Z = void;
template<typename> struct Zermelo;
template<typename N> using Successor = Zermelo<N>;
A better test in my eyes would be to ask if the given implementation has runtime effects. If a template struct or alias does not contain any definition with an effect only happening at runtime, it's probably template meta programming.
Closing words
Of course normal template programming might utilize meta template programming. You can use meta template programming to determine properties of normal template arguments.
For example you might choose different output strategies (assuming some meta-programming implementation of template<class Iterator> struct is_pointer_like;
template<class It> generateSomeData(It outputIterator) {
if constexpr(is_pointer_like<outputIterator>::value) {
generateFastIntoBuffer(static_cast<typename It::pointer> (std::addressof(*outputIterator));
} else {
generateOneByOne(outputIterator);
}
}
This constitutes template programming employing the feature implemented with meta template programming.
Where do normal templates end and meta templates begin?
When the code generated by templates rely on the fundamental aspects of programming, such as branching and looping, you have crossed the line from normal templates to template meta programming.
Following the description from the article you linked:
A regular function
bool greater(int a, int b)
{
return (a > b);
}
A regular function that works with only one type (ignoring implicit conversions for the time being).
A function template (generic programming)
template <typename T>
bool greater(T a, T b)
{
return (a > b);
}
By using a function template, you have created generic code that can be applied to many types. However, depending on its usage, it may not be correct for null terminated C strings.
Template Metaprogramming
// Generic implementation
template <typename T>
struct greater_helper
{
bool operator(T a, T b) const
{
return (a > b);
}
};
template <typename T>
bool greater(T a, T b)
{
return greater_helper<T>().(a > b);
}
// Specialization for char const*
template <>
struct greater_helper<char const*>
{
bool operator(char const* a, char const* b) const
{
return (strcmp(a, b) > 0);
}
};
Here, you have written code as if to say:
If T is char const*, use a special function.
For all other values of T, use the generic function.
Now you have crosses the threshold of normal templates to template metaprogramming. You have introduced the notion if-else branching using templates.

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.

Trait which checks whether class has typedef (private or other) or not

Is there a way to check if class has a typedef which works even for private typedef?
Following code works in VS2013, but fails on ideone's gcc
template<typename T>
struct to_void
{
typedef void type;
};
class Foo
{
typedef int TD;
};
template <typename T, typename dummy = void>
struct has_TD : std::false_type {};
template <typename T>
struct has_TD<T, typename to_void<typename T::TD>::type > : std::true_type{};
int main()
{
std::cout << std::boolalpha << has_TD<Foo>::value << std::endl;
}
edit - why I want this
I have custom serialization system, which can serialize arbitrary type. It has several overloads when it must behave differently (for example string). For the rest of the types, it simply writes the value in the memory. If I have composed type, I can sometimes just write into memory as well (save & load happens on the same architecture, compiled with the same compiler, so paddings will be the same, etc.). This method is valid for example for POD types (std::is_pod trait), but all POD types is only a subset of all types, supporting this serialization.
So I basically have templated function write<T> which just write sizeof(T) bytes (raw-serialization)... But I don't want this to be called by mistake, I want user, to explicitly say in their class: "this class/struct can be raw-serialized"). The way I do it is a macro ALLOW_RAW_SERIALIZE which defines some typedef which can be checked via trait. If class MyClass doesn't contains typedef, calling write(myClassInstance) will produce compiler error.
The things which which basically decide if class can be raw-serialized are its members (without reflection, members cannot be enumerated and checked automatically, so user have to provide such information). typical class looks like this:
class
public
ctor-dtor
methods
private
methods
members
and I want users to allow write ALLOW_RAW_SERIALIZE as close to the members as possible, so when they change some members there is a lesser chance to forgot about updating ALLOW_RAW_SERIALIZE (remove it. when it's no longer valid)
So that is why I want to check a private typedef
Since it's substitute for reflection and takes whole type and write it, I don't fell about it like breaking encapsulation or so...
UPDATE:
Okay, did a little research.
FYI, the [probable] reason that ideone didn't compile is that what you're doing needs -std=c++11 [or higher]. I got similar errors before adding that. But, I had to use clang++ as g++ still had problems compiling if TD was private.
But, I'm not sure this works as the only combo that printed true was if TD was public. All others of public/private and changing TD to TF produced false. Maybe VS2013 works [why?], but two other compilers have issues, either in compilation or runtime results--YMMV.
The basis for what you're doing is std::integral_constant [since c++11]. There appears to be no standard derivation from this for what you're doing. That is, from http://www.cplusplus.com/reference/type_traits/integral_constant/ the list of type traits [on the left] has nothing that matches your use case [AFAICT].
Nor does Boost.TypeTraits have anything that matches up [again, AFAICT].
From Andrei Alexandrescu's book: "Modern C++ Design: Generic Programming and Design Patterns Applied", section 2.10 Type Traits:
Usually, you will write your own trait templates and classes as your generic code needs them. Certain traits, however, are applicable to any type. They can help generic programmers to tailor template code better to the capabilities of a type.
So, it's "okay" to roll your own, if you wish.
But, even the TypeTraits he talks about [from Loki], again, doesn't have anything that matches what you're doing.
Since neither std nor Boost has anything, then the question becomes "what is standard?" [from your perspective]. There may be "fludger" c++ traits library somewhere that has an implementation, but would that be considered "standard"? YMMV
However, a question or two:
Why would one do this? What is the use for it? What about a protected typedef in a base class?
And, this seems to require knowledge of the private part of a class, and wouldn't that be a violation of either "data hiding" or encapsulation [without a friend declaration of some sort]?
So, if that last question is true, the probable [IMO] answer is that there is no standard way to do this, because it's not something one should be doing in a standard library.
Side note: This is the part that got downvoted (before I [truly] understood the question). I believe I've acquitted myself above. So, disregard the answer below.
When you use class the default visibility is private. With struct, it's public.
So, either do:
struct Foo
Or:
class Foo
{
public:
typedef int TD;
};
This is, of course, assuming that you want TD to be public
If all you need is compile time checking then following code should do:
#include <iostream>
class Foo
{
typedef int TD;
template<typename T> friend class has_TD;
};
template <typename T>
struct has_TD
{
typedef typename T::TD type;
};
template <typename T, typename has_TD<T>::type = 0>
void write(const T& /*data*/)
{
std::cout << "serialize" << std::endl;
}
int main()
{
Foo foo;
write(foo);
}

Using enum as template type argument in C++

are there any restrictions / problems using an enum as template (type) argument in C++?
Example:
enum MyEnum
{
A, B, C, D, E
};
template <typename _t>
class MyTemplate
{
public:
_t value;
void func(const _t& param) { /* .... */ }
};
// ....
MyTemplate<MyEnum> MyInstance;
My actual problem using MSVC++ via VS 2008 (SP1) on Win32/x86 are several compilation errors (= errors reported by the compiler) in association with classes using enums as template arguments. As my project unfortunately has become a bit complex (you can consider that as a design error :P), the template classes raising these errors are derived, nested and even specialised on a class with enum template parameter.
Trying to build, the compiler reports many wrong/useless errors such as "C2059: syntax error: 'public'" in lines where there is only a comment. Many of them I could fix by replacing in methods similar to the one in the example the const _t& param by _t (i.e. copying the parameter), but neither could I fix all of these errors nor do I have a clue why this "helps". **I know, the simple example above compiles w/o errors.
Using int instead of enum, my project compiles w/o errors.
Thanks in advance for any hint or tip!
Edit:
After all, I seriously consider this as a compiler bug. When I tried to reproduce the errors with simplified code, I got them only in 50 % of all "builds", not very deterministic:
E.g. tried to compile, and it reported these errors. Rebuild - no change. Deleted a comment, build - no change. Rebuild - and then: no errors, compiles fine.
I've already met a few compiler bugs (2 or 3 I guess within 20k lines of code), but this one seems to me very strange.
Any suggestions how to figure out if it is the compiler?
Yes, there are restrictions. For example, you cannot use an anonymous enum as a template argument according to C++03 14.3.1[temp.arg.type]/2
A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.
So the following code is not valid in C++03:
template <typename T>
void f(T) {}
enum {A};
int main() {
f(A);
}
It is valid in C++11 though.
Referring to the original question:
are there any restrictions / problems using an enum as template (type) argument in C++?
I didn't find any - and I don't think there are any. It might turn out to be a bad idea because this technique it is not used that often, so there might be a few (more) compiler bugs relating to this, just as Potatoswatter said.
Consider the following example:
enum MyEnum : int
{
A, B, C, D
};
template <typename _t> class MyTemplate
{
public:
void print()
{
cout << "not using any specialisation" << endl;
}
};
template <> class MyTemplate <MyEnum>
{
public:
void print()
{
cout << "MyEnum specialisation" << endl;
}
};
template<> class MyTemplate <int>
{
public:
void print()
{
cout << "int specialisation" << endl;
}
};
template <typename _t> void print(_t param)
{
MyTemplate<_t> m;
m.print();
}
int main()
{
print(A);
print(5);
return 0;
}
The output is:
MyEnum specialisation
int specialisation
For these simple examples, everything works fine and as expected and the enum works perfectly as any other type as template type argument (= I don't see any reason for problems).
Originally, I introduced the example in the question to show what I meant with that question (enum as template type argument, show possible usages as member or method argument type and so on). To provide a bit of background, i.e. why I asked that question (imagine I asked "are there any problems with int"), I mentioned these strange problems compiling my actual project.
I'm sorry I could not extract a snippet of it that is complete in itself and reproducing the errors, the least I could get were 2k lines of code splitted into 4 files, where a "syntax error : 'public'" and some other syntax error were raised when I compiled the project, and they appeared / disappeared under certain circumstances, when deleting a comment or re-building (= deleting the intermediate files). Unfortunately, rebuilding does not help with the original project, where I had to replace a specialisation from an enum type to int.
So, thanks everyone for your hints and tips. The underlying problem seems to me to be a compiler bug, what makes the question a bit pointless, as the answer seems to be just "no - there are no restrictions using an enum as template type argument". Sorry for the inconvenience.
MSVC handles enum (value) template parameters strangely. Enums are promoted to int improperly sometimes and the operators aren't defined properly. It seems that they don't really test the template engine with enum types.
Proving it's a compiler bug is simple: put valid code in and observe whether it successfully compiles. Your example is obviously compliant, so the problem (or the mistake, anyway) is theirs.
Edit: on closer inspection you say that the example does not reproduce the bug. Neither we nor anyone else can help you until you produce an example that does.

Test whether a class is polymorphic

We have a sub-project 'commonUtils' that has many generic code-snippets used across the parent project.
One such interesting stuff i saw was :-
/*********************************************************************
If T is polymorphic, the compiler is required to evaluate the typeid
stuff at runtime, and answer will be true. If T is non-polymorphic,
the compiler is required to evaluate the typeid stuff at compile time,
whence answer will remain false
*********************************************************************/
template <class T>
bool isPolymorphic() {
bool answer=false;
typeid(answer=true,T());
return answer;
}
I believed the comment and thought that it is quite an interesting template though it is not
used across the project. I tried using it like this just for curiosity ...
class PolyBase {
public:
virtual ~PolyBase(){}
};
class NPolyBase {
public:
~NPolyBase(){}
};
if (isPolymorphic<PolyBase>())
std::cout<<"PolyBase = Polymorphic\n";
if (isPolymorphic<NPolyBase>())
std::cout<<"NPolyBase = Also Polymorphic\n";
But none of those ever returns true. MSVC 2005 gives no warnings but Comeau warns typeid expression has no effect. Section 5.2.8 in the C++ standard does not say anything like what the comment says i.e. typeid is is evaluated at compile time for non-polymorphic types and at runtime for polymorphic types.
1) So i guess the comment is misleading/plain-wrong or since the author of this code is quite a senior C++ programmer, am i missing something?
2) OTOH, I am wondering if we can test whether a class is polymorphic(has at least one virtual function) using some technique?
3) When would one want to know if a class is polymorphic? Wild guess; to get the start-address of a class by using dynamic_cast<void*>(T) (as dynamic_cast works only on polymorphic classes).
Awaiting your opinions.
Thanks in advance,
I cannot imagine any possible way how that typeid could be used to check that type is polymorphic. It cannot even be used to assert that it is, since typeid will work on any type.
Boost has an implementation here. As for why it might be necessary -- one case I know is the Boost.Serialization library. If you are saving non-polymorphic type, then you can just save it. If saving polymorphic one, you have to gets its dynamic type using typeid, and then invoke serialization method for that type (looking it up in some table).
Update: it appears I am actually wrong. Consider this variant:
template <class T>
bool isPolymorphic() {
bool answer=false;
T *t = new T();
typeid(answer=true,*t);
delete t;
return answer;
}
This actually does work as name suggests, exactly per comment in your original code snippet. The expression inside typeid is not evaluated if it "does not designate an lvalue of polymorphic class type" (std 3.2/2). So, in the case above, if T is not polymorphic, the typeid expression is not evaluated. If T is polymorphic, then *t is indeed lvalue of polymorphic type, so entire expression has to be evaluated.
Now, your original example is still wrong :-). It used T(), not *t. And T() create rvalue (std 3.10/6). So, it still yields an expression that is not "lvalue of polymorphic class".
That's fairly interesting trick. On the other hand, its practical value is somewhat limited -- because while boost::is_polymorphic gives you a compile-time constant, this one gives you a run-time value, so you cannot instantiate different code for polymorphic and non-polymorphic types.
Since C++11, this is now available in the <type_traits> header as std::is_polymorphic. It can be used like this:
struct PolyBase {
virtual ~PolyBase() {}
};
struct NPolyBase {
~NPolyBase() {}
};
if (std::is_polymorphic<PolyBase>::value)
std::cout << "PolyBase = Polymorphic\n";
if (std::is_polymorphic<NPolyBase>::value)
std::cout << "NPolyBase = Also Polymorphic\n";
This prints just "PolyBase = Polymorphic".
class PolyBase {
public:
virtual ~PolyBase(){}
};
class NPolyBase {
public:
~NPolyBase(){}
};
template<class T>
struct IsPolymorphic
{
struct Derived : T {
virtual ~Derived();
};
enum { value = sizeof(Derived)==sizeof(T) };
};
void ff()
{
std::cout << IsPolymorphic<PolyBase >::value << std::endl;
std::cout << IsPolymorphic<NPolyBase>::value << std::endl;
}
One can use the facts that:
dynamic_cast fails at compile time if the argument is not a polymorphic class. So that it can be used with SFINAE.
dynamic_cast<void*> is a valid cast that returns the address of the complete polymorpic object.
Hence, in C++11:
#include <iostream>
#include <type_traits>
template<class T>
auto is_polymorphic2_test(T* p) -> decltype(dynamic_cast<void*>(p), std::true_type{});
template<class T>
auto is_polymorphic2_test(...) -> std::false_type;
template<class T>
using is_polymorphic2 = decltype(is_polymorphic2_test<T>(static_cast<T*>(0)));
struct A {};
struct B { virtual ~B(); };
int main() {
std::cout << is_polymorphic2<A>::value << '\n'; // Outputs 0.
std::cout << is_polymorphic2<B>::value << '\n'; // Outputs 1.
}
I'm a little confused here, and am hoping to get some comments on this answer explaining what I'm missing.
Surely if you want to find out whether a class is polymorphic, all you have to do is ask whether it supports dynamic_cast, isn't that right?
template<class T, class> struct is_polymorphic_impl : false_type {};
template<class T> struct is_polymorphic_impl
<T, decltype(dynamic_cast<void*>(declval<T*>()))> : true_type {};
template<class T> struct is_polymorphic :
is_polymorphic_impl<remove_cv_t<T>, void*> {};
Can anyone point out a flaw in this implementation? I imagine there must be one, or must have been one at some point in the past, because the Boost documentation continues to claim that is_polymorphic "can't be portably implemented in the C++ language".
But "portably" is kind of a weasel word, right? Maybe they're just alluding to how MSVC doesn't support expression-SFINAE, or some dialects such as Embedded C++ don't support dynamic_cast. Maybe when they say "the C++ language" they mean "a lowest-common-denominator subset of the C++ language." But I have a nagging suspicion that maybe they mean what they say, and I'm the one who's missing something.
The typeid approach in the OP (as amended by a later answer to use an lvalue not an rvalue) also seems fine, but of course it's not constexpr and it requires actually constructing a T, which might be super expensive. So this dynamic_cast approach seems better... unless it doesn't work for some reason. Thoughts?