I am trying to understand the concept of type traits.
Say i have some templatized Class Hierachy like this and a client function:
template<typename T>
class Base
{
public:
//...
virtual bool inline isSymmetric() const = 0;
};
template<typename T>
class ChildrenOperation : public Base<T>
{
public:
//...
virtual bool inline isSymmetric() const override
{
return true;
}
};
template<typename T>
void clientFunction(const Base<T>& operation)
{
//...
if(operation.isSymmetric())
{
// use operation in one way
} else {
// use operation in another way
}
}
Obviously, clientFunction is polymorphic and different children can have different implementations of isSymmetric.
However, since isSymmetric seems to be constant and really more of a type information, i've read about type traits and i was wondering whether it is possible to rewrite the client function to not depend on isSymmetric on runtime, but rather compile time.
I've tried adding a trait like this. But i am not sure how to specialize it and use it in a polymorphic context.
template <typename T>
struct is_symmetric {
static const bool value = false;
};
If being symmetric depends on the concrete type derived from Base, then you cannot use a type traits for this situation. Type traits are evaluated in compile time, so if you have a polymorphic type which's traits are not known at compile time, then you cannot use type traits.
One possible solution, if the symmetricity is really constant, is this:
class Base {
public:
Base(bool symmetric) : symmetric(symmetric) {}
bool isSymmetric() {
return symmetric;
}
// ...
private:
bool symmetric;
};
class ChildrenOperation : public Base {
public:
ChildrenOperation() : Base(true) {}
// ...
};
I did not use the templates here because they are irrelevant in this case. Of course, if symmetricity depends on T then you can use type traits, like this:
template <typename T>
struct is_symmetric : public std::false_type {};
template <>
struct is_symmetric<SymmetricT> : public std::true_type {};
So the solution depends on whether the trait depends only on the dynamic type of the object, in which case you should use the fist code, the template parameter, in which case you should use the second code, or both. From your example, it's not entirely clear which is your situation.
Related
I was thinking about about template specialization and was wondering if there was a way to use partial specialization to generate two different code paths that are automatically merged.
In this case I have a computational engine where I want an enum to select different functions at compile-time. In this case, depending on the policy or scheme I want different functions at compile-time.
I was thinking that I could avoid explicitly partially specializing all variants. Is this possible?
I've included a small code sample.
#include <iostream>
enum class scheme { linear, polynomial };
enum class policy { no_checking, raise_exception };
struct computational_base
{
void left();
void middle();
void do_stuff()
{
left();
middle();
}
};
template <scheme scheme, policy left>
struct computational_backend : public computational_base
{
};
template <policy left>
struct computational_backend<scheme::linear, left> : public computational_base
{
void middle()
{
std::cout << "scheme::linear" << std::endl;
}
};
template <scheme scheme>
struct computational_backend<scheme, policy::no_checking> : public computational_base
{
void left()
{
std::cout << "policy::no_checking" << std::endl;
}
};
int main()
{
//Ideally would select middle() from first template, and left() from second template
// more than one partial specialization matches the template argument list
computational_backend<scheme::linear, policy::no_checking> what;
what.do_stuff();
return 0;
}
CRTP and multiple inheritance can be your friend. At the core, you can use multiple inheritence to bring functionality in from both classes
template <scheme s, policy p>
struct computational_backend
: scheme_backend<s>
, policy_backend<p>
{ };
This sort of thing will work, as long as the different parts of the computational process don't need to call eachother. In other words, it works when middle() never needs to call left(), and vice versa.
If you need them to call each other, the Curiously Recursive Template Pattern (CRTP) is your friend. This is an oddity which basically lets you cast to the most derived type from the base classes because you pass that most derived type in as a template parameter. It looks like this:
template <typename DerivedT, scheme s>
struct scheme_backend;
template <typename DerivedT, policy p>
struct policy_backend;
template <typename DerivedT>
struct scheme_backend<DerivedT, scheme::linear>
{
DerivedT& derived()
{
return *static_cast<DerivedT*>(this);
}
void left()
{
...
derived().middle();
...
}
};
template <scheme s, policy p>
struct computational_backend
: scheme_backend<computational_backend<s, p>, s>
, policy_backend<computational_backend<s, p>, p>
{ };
I only drew one of the specializations, but you get the idea. It turns out that strange static cast is not only legal in C++, it is, in fact, extraordinarily fast. In many cases, the compiler can optimize it away completly.
I was wondering how we can declare an interface in C++ without using virtual functions. After some internet searching I put together this solution:
#include <type_traits>
using namespace std;
// Definition of a type trait to check if a class defines a member function "bool foo(bool)"
template<typename T, typename = void>
struct has_foo : false_type { };
template<typename T>
struct has_foo<T, typename enable_if<is_same<bool, decltype(std::declval<T>().foo(bool()))>::value, void>::type> : true_type { };
// Definition of a type trait to check if a class defines a member function "void bar()"
template<typename T, typename = void>
struct has_bar : false_type { };
template<typename T>
struct has_bar<T, typename enable_if<is_same<void, decltype(std::declval<T>().bar())>::value, void>::type> : true_type { };
// Class defining the interface
template <typename T>
class Interface{
public:
Interface(){
static_assert(has_foo<T>::value == true, "member function foo not implemented");
static_assert(has_bar<T>::value == true, "member function bar not implemented");
}
};
// Interface implementation
class Implementation:Interface<Implementation>{
public:
// If the following member functions are not declared a compilation error is returned by the compiler
bool foo(bool in){return !in;}
void bar(){}
};
int main(){}
I'm planning to use this design strategy in a project where I will use static polymorphism only.
The C++ standard I will use in the project is C++11.
What do you think are the pros and cons of this approach?
What improvements can be made on the code I proposed?
EDIT 1:
I just realised that inheriting from Interface is not needed. This code could also be used:
class Implementation{
Interface<Implementation> unused;
public:
bool foo(bool in){return !in;}
void bar(){}
};
EDIT 2-3:
One major difference between the static_assert solution (with or without CRTP) and the standard CRTP is that the CRTP does not guarantee that the derived class implements all the interface members. E.g., the following code compiles correctly:
#include <type_traits>
using namespace std;
template< typename T>
class Interface{
public:
bool foo(bool in){
return static_cast<T*>(this)->foo(in);
}
void bar(){
static_cast<T*>(this)->bar();
}
};
class Implementation: public Interface<Implementation>{
public:
// bool foo(bool in){return !in;}
// void bar(){}
};
int main(){}
An error about a missing member function will be returned by the compiler only when the functions foo or bar will be required.
The way I see it, the static_assert solution feels more like an interface declaration than CRTP alone.
An common way to implement static polymorphism is to use CRTP.
With this pattern, you define an templated interface class, whose methods forward to the template:
// Interface
template <typename T>
struct base {
void foo(int arg) {
static_cast<T*>(this)->do_foo(arg);
}
};
You implementation the inherits from the base class and implements the methods:
// Implementation
struct derived : base<derived> {
void do_foo(int arg) {
std::cout << arg << '\n'
}
};
This pattern has the advantage that it looks "feels" a lot like regular runtime polymorphism, and the error messages are generally quite sane. Because all the code is visible to the compiler, everything can be inlined so there's no overhead.
It appears that you want to implement concepts (lite). You may want to read the article before attempting an implementation.
Absent compiler support, you can partially implement this idea. Your static_assert idea is a known way to express interface requirements.
Consider the Sortable example from the link. You can create a class template Sortable, use static_assert to assert all kind of thinks about the template parameter. You explain to your users that they need to implement a certain cet of methods, and to enforce that set is implemented, they need to make use of Sortable<TheirClass> one way or another.
In order to express, right in a function declaration. the idea that your function requires a Sortable, you will have to resort to something like this:
template <typename Container>
auto doSomethingWithSortable (Container&) -> std::enable_if<Implements<Container, Sortable>>::type;
So I have run into a problem in which I need a method to be defined for any types that inherit from a base class that I have created, yet I need that method to be static, is there anyway I can force it to be created?
The reason I need this I will have people be extending my base class, but I need to be able to guarantee a call to a function like so derivedType derivedType::createFromSerialized(std::string) will work to create a new instance from a serialization.
Edit: I am trying to follow Richard J. Ross III's advice and use static_assert however I am running into some problems with that and I have a feeling its due to it being called from a templated class but I can't figure out how to fix it.
template <typename indType> class population {
static_assert(std::is_function<indType::createFromSerialized>::value, "message");
....
};
However that is giving me an error of to refer to a type member of a template parameter, use ‘typename indType:: createFromSerialized’ and no type named 'createFromSerialized' in 'class test'
The reason I am trying to use static_assert is to get a nicer error message that will give information about the proper function signature for createFromSerialized instead of just one that says its not defined.
This can be done by combining static_assert and SFINAE detection technique.
template<typename T, typename V = bool>
struct has_deserialize : std::false_type { };
template<typename T>
struct has_deserialize<T,
typename std::enable_if<
std::is_same<decltype(&T::createFromSerialized),
T* (*)(const std::string&)>::value,
bool
>::type
> : std::true_type { };
template <typename T>
class test
{
static_assert(has_deserialize<T>::value, "No suitable createFromSerialized");
};
What you are trying to accomplish is possible through a factory pattern very easily. Not sure whether you can accomplish it using templates.
Here's a skeleton of how I would go about implementing the serialization functionality.
SerializationFunctor.h
class Base;
class SerializationFunctor
{
virtual Base* operator(FILE* in) const = 0;
};
Base.h
class Base
{
bool registerSerializationFunction(std::string const& identifier,
SerializationFunctor* functor);
};
ConcreteA.h
class ConcreteA
{
};
ASerializationFunctor.cc
class ASerializationFunctor : public SerializationFunctor
{
virtual Base* operator(FILE* in)
{
// Restore ConcreteA and return a pointer.
}
};
bool dummy = registerSerializationFunction("ConcreteA", new ASerializationFunctor());
ConcreteB.h
class ConcreteB
{
};
BSerializationFunctor.cc
class BSerializationFunctor : public SerializationFunctor
{
virtual Base* operator(FILE* in)
{
// Restore ConcreteB and return a pointer.
}
};
bool dummy = registerSerializationFunction("ConcreteB", new BSerializationFunctor());
I want to do:
template <class Derived=BattleData>
class BattleData : public BattleCommandManager<Derived> {
};
But obviously BattleData isn't declared, so I tried a forward declaration:
template <class T> class BattleData;
template <class Derived=BattleData>
class BattleData : public BattleCommandManager<Derived> {
};
But then I get
error: "wrong number of template parameter on the second line, with
BattleData.
I really fail to see a solution to this!
Edit:
The reason I'm doing this is because I want to be able to use BattleData directly as a class, but I also want to be able to subclass it in which case I have to specify the derived class as the second template parameter.
For example let's say the corpus of my BattleData class is :
template <class Derived> class BattleData: public BaseClass<Derived> {
void foo1(){};
void foo2(){};
void foo3(){};
}
And I have a subclass
template class SubBattleData: public BattleData<SubBattleData> {
void foo1(){};
}
I would still want, in some cases, to be able to write code like this:
BattleData *x = new BattleData(...);
I can't even do the following without being able to use default arguments:
BattleData<BattleData> *x = new BattleData<BattleData>(...);
On one side, the reason functions aren't virtualized in the BattleData class is the benefit of having no virtual function. The other reason it doesn't work for me is that one of the parent CRTP classes invokes functions only if they're present in the derived type (using decltype(Derived::function) and enable-if like structures), and fall back to default behavior otherwise. Since there can be a great deal of those functions with a particular design pattern (like a CRTP that reads a protocol with many different cases and processes a case a particular way only if the derived class specify the corresponding function, otherwise just transfer it without processing).
So those functions can be present in SubBattleData and not BattleData, but both classes would work fine if instantiated, yet it's impossible to instantiate BattleData.
You should be able to accomplish your original design goals more naturally than the above. You can't use the actual Derived typename as the default clearly because what you're really trying to write is the following:
template <class Derived=BattleData <BattleData <BattleData <...>>>
class BattleData : public BattleCommandManager<Derived> {
};
You get the idea. Instead, just use a placeholder like void:
template <typename T = void>
class BattleData : public BattleCommandManager <
typename std::conditional <
std::is_same <T, void>::value,
BattleData <void>,
T
>::type>
{
};
Disclaimer: I did not compile the above.
Can't you use an Empty class for the second template parameter?
template <class T=DataContainer, class Derived=BattleData<T, Empty> >
class BattleData : public BattleCommandManager<Derived> {
};
I don't see what you are trying to do. What is wrong with
template <class T=DataContainer>
class BattleData : public BattleCommandManager< BattleData<T> > {
};
If you specify Derived to be something else than the actual derived class static polymorphism is not going to work and CRTP becomes somewhat useless anyway.
Edit: From what I have gathered this is what you want to in abstract terms:
template <class Derived>
struct Base {
void interface() {
static_cast<Derived*>(this)->implementation();
}
};
template<typename T>
struct Derived : Base<Derived> {
// dummy so we get you example
T t;
void implementation() {
std::cout << "derived" << std::endl;
}
};
struct Derived2 : public Derived<int> {
// hide implementation in Derived
// but still have Base::interface make the right call statically
void implementation() {
std::cout << "derived2" << std::endl;
}
};
There is no way I know of that you can make this work. Another
approach would be to use policy classes instead of CRTP. They are
compatible with inheritance and you can achieve similar behaviour.
template<typename Policy>
struct BattleCmdManager : public Policy {
using Policy::foo;
};
template<typename T>
struct BattleData {
// ...
protected:
void foo();
};
struct BattleData2 : public BattleData<int {
// ...
protected:
void foo();
};
Here is how I solved it:
template <class Derived> class BattleDataInh: public BaseClass<Derived> {
void foo1(){};
void foo2(){};
void foo3(){};
};
template class SubBattleData: public BattleDataInh<SubBattleData> {
void foo1(){};
};
class BattleData : public BattleDataInh<BattleData> {
};
And that way, I can add any other template parameters too. The solution was in front of my eyes the whole time but I didn't see it...
I'm building a datastructure class with an std-like interface, and implementing different iterators for the data structure.
Conceptually, what I would like to do is something like this:
template <class DataT>
class DataStructure
{
protected:
DataT& Data;
public:
DataStructure(DataT& data) : Data(data) {}
class BaseIterator
{
public:
BaseIterator()
{
cout<<"BaseIterator"<<endl;
}
};
class DerrivedIterator1 : public BaseIterator
{
public:
DerrivedIterator1()
{
cout<<"DerrivedIterator1"<<endl;
}
};
class DerrivedIterator2 : public BaseIterator
{
public:
DerrivedIterator2()
{
cout<<"DerrivedIterator2"<<endl;
}
};
template<class IterT>
IterT Begin()
{
//none-specialized implementation. Possibly throw exception
}
template<>
DerrivedIterator1 Begin<DerrivedIterator1>()
{
//Find beginning for DerrivedIterator1
}
template<>
DerrivedIterator2 Begin<DerrivedIterator2>()
{
//Find beginning for DerrivedIterator1
}
};
But this of course does not compile since C++ doesn't allow to specialize template member functions in none-specialized template containers.
The obvious workaround is of course to declare 2 different functions: Begin_Iterator1 and Begin_Iterator2 and be done with it. But I'm looking for a workaround that doesn't change the interface.
Any ideas?
Edit: I forgot to mention that this is for a HW assignment and so boost and even std is not an option.
Function templates cannot be specialized in C++, point.
It does not matter whether they are members of template or not, specialization of function templates is not allowed. Normally when using argument types to infer the template arguments, overloading does the same specialization would, so specialization for functions (and the associated extra complexity in overload resolution and such) was not deemed necessary.
You however don't have any arguments to infer on and would instantiate the templates manually. No,
DataStructure::DerivedIterator1 i = dataStructure.Begin();
would not work as you wrote the code, because type inference, just like overload resolution is only done on the arguments, not expected return value. You'd have to write:
DataStructure::DerivedIterator1 i = dataStructure.Begin<DataStructure::DerivedIterator1>();
and that has zero benefit over:
DataStructure::DerivedIterator1 i = dataStructure.BeginIterator1();
However, the first expression can be made to work with some wizardry. First you have to define BeginIterator1 and BeginIterator2 and than you'd do a temporary to late-decide which one to construct:
class DataStructure {
...
class BeginIteratorConstructor {
DataStructure &dataStructure;
public:
BeginIteratorConstructor(DataStructure &ds) : dataStructure(ds) {}
operator DerivedIterator1() { return dataStructure.BeginIterator1(); }
operator DerivedIterator2() { return dataStructure.BeginIterator2(); }
};
BeginIteratorConstructor Begin() { return BeginIteratorConstructor(*this); }
...
};
Now dataStructure.Begin() will return a temporary something, that will call BeginIterator1 if you cast it to DerivedIterator1 or call BeginIterator2 when you cast it to DerivedIterator2. If you pass it to something where the compiler can't decide which one to cast to, it will die either because of ambiguous overload or because BeginIteratorConstructor is not in fact iterator and you'll have to cast it explicitly.
(You should carefully make as much of the BeginIteratorConstructor private, but I am not sure how far will the compiler allow you to go, so you'd have to experiment a bit)
You can use a tagging system, which will save you from partially specialized functions inside class templates:
struct base_iter_tag{};
struct der1_iter_tag{};
struct der2_iter_tag{};
template<class T>
struct iter_type;
template<>
struct iter_type<BaseIterator>{
typedef base_iter_tag tag;
};
template<>
struct iter_type<DerivedIterator1>{
typedef der1_iter_tag tag;
};
template<>
struct iter_type<DerivedIterator2>{
typedef der2_iter_tag tag;
};
template<class IterT>
IterT Begin(){
return DoBegin(typename iter_type<IterT>::tag());
}
BaseIterator DoBegin(base_iter_tag){
// ...
}
DerivedIterator1 DoBegin(der1_iter_tag){
// ...
}
DerivedIterator2 DoBegin(der2_iter_tag){
// ...
}
This is essentially what the standard library does with the iterator_traits<T>::iterator_category and overloaded functions depending on the category (e.g. forward_iterator_tag, random_access_iterator_tag, etc...).