I am writing a C++ wrapper for a C library that works with handles represented by integers. There are a bunch of open functions (Aopen, Bopen, Copen, Dopen, Eopen, ...) and corresponding close functions (Aclose, Bclose, Cclose, Dclose, Eclose, ...). I currently have wrapper classes implementing basic RAII, but I have a bit of code duplication, as each of these wrappers differs only in which open and close routine it calls. To get rid of this duplication I was thinking of templating on an enum I define with values for each of the routines (e.g. Atype, Bytpe, etc), and then selecting the correct open and close function at compile time. It would like something like:
TypeWrapper<AType> wrapped_a(...)
TypeWrapper<BType> wrapped_b(...)
...
Is this a reasonable approach, is there a simpler approach, or is there a name for this type of construction?
Thank you!
You may do something like the following:
template <typename H, H Open(const char*), void Close(H)>
class Wrapper
{
public:
Wrapper(const char* file) : h(Open(file)) {}
~Wrapper() { Close(h); }
Wrapper(const Wrapper&) = delete;
Wrapper& operator = (const Wrapper&) = delete;
private:
H h;
};
And then using Wrapper_A = Wrapper<AHandle, AOpen, AClose>;
Live example
What you're looking for is Template Specialization.
Basically, this is done by templating your TypeWrapper class on an enum value, then providing specialized implementations for the open/close calls for each enum value.
An example is worth a thousand words: live example
#include <iostream>
using namespace std;
enum Type {
AType = 0,
BType,
CType,
};
void AOpen() { std::cout << "A open." << std::endl; }
void BOpen() { std::cout << "B open." << std::endl; }
void COpen() { std::cout << "C open." << std::endl; }
template<Type T>
class TypeWrapper {
public:
void open();
void close();
};
template<>
void TypeWrapper<AType>::open() { AOpen(); }
template<>
void TypeWrapper<BType>::open() { BOpen(); }
template<>
void TypeWrapper<CType>::open() { COpen(); }
int main() {
TypeWrapper<AType> wrapped_a;
TypeWrapper<BType> wrapped_b;
wrapped_a.open();
wrapped_b.open();
return 0;
}
Related
In some code that I was reading, I found the usage of empty struct like so:
struct input_iterator_tag { };
struct bidirectional_iterator_tag { };
struct random_access_iterator_tag { };
So in the rest of the code, it was used as what they call tag dispatching.
I was wondering if there is other usage of empty structs.
from an older post I saw that :
three major reasons we use empty structs in C++ are:
a base interface
a template parameter
a type to help overload resolution. (tag dispatching if I am not wrong)
Could someone explain that please?
a type to help overload resolution. (tag dispatching if I am not wrong)
When you want to use a complex template specialization pattern on some function, you don't try to go at it directly, but rather write:
template <typename T1, typename T2, other things maybe>
int foo(T1 param1, T2 param2 and so on)
{
using tag = put your complex stuff here, which produces an empty struct
detail::foo_impl(tag, std::forward<T1>(param1), std::forward<T2>(param2) and so on);
}
Now, the compiler doesn't have to decide between competing choices of template specialization, since with different tags you get incompatible functions.
a base interface
struct vehicle {
// common members and methods,
// including (pure) virtual ones, e.g.
virtual std::size_t num_maximum_occupants() = 0;
virtual ~vehicle() = default;
};
namespace mixins {
struct named { std::string name; };
struct wheeled { int num_wheels; public: rev() { }; };
} // namespace mixins
struct private_sedan : public vehicle, public wheeled, named {
// I dunno, put some car stuff here
//
// and also an override of `num_maximum_occupants()`
};
Making the base struct completely empty is perhaps not that common, but it's certainly possible if you use mixins a lot. And you could check for inheritance from vehicle (although I'm not sure I'd do that).
a template parameter
Not sure what this means, but venturing a guess:
template <typename T>
struct foo { };
template <typename T, typename N>
struct foo<std::array<T, N>> {
int value = 1;
};
If you now use foo<T>::value in a function, it will work only if T is int with few (?) exceptions.
I also tried to come up with examples:
as a base interface
// collection of very abstract vehicles
#include <vector>
struct Vehicle {};
struct Car : Vehicle {
int count_of_windows;
};
struct Bike : Vehicle {
int size_of_wheels;
};
std::vector<Vehicle> v{Bike{}, Car{}};
as a template parameter
// print same number in 3 different formats
#include <iostream>
struct dec {};
struct hex {};
struct octal {};
template<typename HOW = dec>
void print_me(int v);
template<>
void print_me<dec>(int v) {
auto f = std::cout.flags();
std::cout << std::dec << v << std::endl;
std::cout.flags(f);
}
template<>
void print_me<hex>(int v) {
auto f = std::cout.flags();
std::cout << std::hex << v << std::endl;
std::cout.flags( f );
}
template<>
void print_me<octal>(int v) {
auto f = std::cout.flags();
std::cout << std::oct << v << std::endl;
std::cout.flags(f);
}
int main() {
print_me(100);
print_me<hex>(100);
print_me<octal>(100);
}
a type to help overload resolution
// add a "noexcept" qualifier to overloaded function
// the noexcept version typically uses different functions
// and a custom "abort" handler
#include <iostream>
struct disable_exceptions {};
void is_number_1() {
int v;
std::cin >> v;
if (v != 1) {
throw new std::runtime_error("AAAA");
}
}
void is_number_1(disable_exceptions) noexcept {
int v;
// use C function - they don't throw
if (std::scanf("%d", &v) != 1) {
std::abort();
}
if (v != 1) {
std::abort();
}
}
int main() {
is_number_1();
is_number_1(disable_exceptions());
}
The example about "tag dispatching" can be found on cppreference iterator_tags. The iterator_category() member of an iterator is used to pick a different overload. That way you could write a different algorithm if for example iterator is forward_iterator, where you can only go forward, or it is a bidirectional_iterator, where your algorithm could change because you may walk back.
Traits are mechanism to mix-in behaviors without using multiple-inheritance.
In C++ Traits are called typeclasses.
Is it possible to use multiple traits (combine them) in C++ code?
I tried to use C++ projects like https://github.com/TartanLlama/typeclasses , but can`t find way to combine multiple Traits.
I also tried code like:
template <typename ... Ts> class(typeclass) trait_combo : public Ts... {};
class(typeclass) printable {
void print();
};
class(typeclass) drawable {
void draw();
};
struct foo {
void print() { std::cout << "foo"; }
void draw() { std::cout << "foo"; }
};
struct bar {
void print() { std::cout << "bar"; }
void draw() { std::cout << "bar"; }
};
std::vector<printable> v;
v.push_back(foo{});
v.push_back(bar{});
v[0].print();
v[1].print();
std::vector<drawable> v1;
v1.push_back(foo{});
v1.push_back(bar{});
v1[0].print();
v1[1].print();
Expected to use multiple traits similar to:
std::vector<trait_combo<printable, drawable>> v2;
v2.push_back(bar{});
v2.push_back(foo{});
Do you know any C++ patterns or projects that allow creation of C++ typeclasses with multiple traits?
I have a non-type template class template<std::size_t N> Derived<N> which derives from some non-template base class Base:
class Base
{
public:
double some_value;
// Some methods and variables that do not depend on N
// I wish to keep these in a non-templated class
virtual const size_t get_N() = 0;
virtual ~Base() = default;
Base(double value): some_value {value} {};
};
template <std::size_t N>
class Derived: public Base
{
public:
double some_other_value;
// Some functions and variables, for which
// the types and actions depend on N
const size_t get_N() override
{
return N;
}
Derived(double value1, double value2): Base(value1), some_other_value {value2} {};
};
Now I have a function call_by_base(Base& my_base), which only uses member variables/functions declared in Base. The only exception to this, is a call to template<std::size_t N> void call_by_derived(Derived& my_derived). Since almost the entire function call_by_base is independent of the template parameter, I would prefer to keep this function non-templated.
I tried to achieve the above with implementations along the lines of:
template<std::size_t N>
void call_by_derived(Derived<N>& my_derived)
{
std::cout << "in call_by_derived" << std::endl;
// Methods that use the functions and variables in Derived.
}
void broken_call_by_base(Base& my_base)
{
std::cout << "in call_by_base" << std::endl;
// Manipulations independent of child
// type Derived<N>
auto derived = dynamic_cast<Derived<my_base.get_N()>&>(my_base);
call_by_derived(derived);
// Manipulations independent of child
// type Derived<N>
}
When I try to compile this code, I get error: expression ‘Base::get_N’ is not a constant-expression. I tried to resolve this error by trying to change different thing, both in my Base and Derived class. This was all without success.
I managed to get the following alternative to work:
void working_call_by_base(Base& my_base)
{
std::cout << "in call_by_base" << std::endl;
if(my_base.get_N()==2)
{
auto derived = dynamic_cast<Derived<2>&>(my_base);
call_by_derived(derived);
}
if(my_base.get_N()==3)
{
auto derived = dynamic_cast<Derived<3>&>(my_base);
call_by_derived(derived);
}
}
This is however very tedious, especially when N can take on many more values. Is there any way to get a function along the lines of broken_call_by_base working? That is: How can I downcast a non-template Base to a non-type template Derived<N>?
ps. Only object of the Derived<N> type will be created. This is the code in main to test:
int main()
{
Derived<3> test(1.0,2.0);
working_call_by_base(test);
broken_call_by_base(test);
call_by_derived(test);
}
It'll be best if you can use a virtual member function to avoid the if/else checks.
If that is not an option for some reason, use of a callback/plugin mechanism is the most appropriate.
You provide a mechanism in the Base-specific code base to allow other classes/functions/modules to register functions that are appropriate for the type they know about.
In the Base-specific code, you keep track of the registered functions using a key that is appropriate for Base.
In the Base-specific code, you check whether a function has been registered for the key. If it has, you call the function with the suitable arguments.
In the derived class specific code, you can downcast to the appropriate class. If the downcast succeeds, in most cases it should, you proceed to use the derived class.
This pattern strictly adheres to the Open-Closed Principle and is one of my favorite coding patterns.
In your case, the key is N.
Here's an example program that demonstrates the concept.
#include <iostream>
// Base.hpp
// #pragma once
#include <cstdint>
class Base
{
public:
double some_value;
// Some methods and variables that do not depend on N
// I wish to keep these in a non-templated class
virtual const size_t get_N() = 0;
virtual ~Base() = default;
Base(double value): some_value {value} {};
typedef void (*CallbackFunctionType1)(Base& b);
static void registerCallback(std::size_t N, CallbackFunctionType1 f);
};
void call_by_base(Base& my_base);
// Base.cpp
#include <map>
namespace BaseNS
{
using CallbackFunctionType1Map = std::map<std::size_t, Base::CallbackFunctionType1>;
CallbackFunctionType1Map& getCallbackFunctionType1Map()
{
static CallbackFunctionType1Map theMap;
return theMap;
}
}
void Base::registerCallback(std::size_t N, CallbackFunctionType1 f)
{
BaseNS::CallbackFunctionType1Map& theMap = BaseNS::getCallbackFunctionType1Map();
theMap[N] = f;
}
void call_by_base(Base& my_base)
{
std::cout << "In call_by_base" << std::endl;
BaseNS::CallbackFunctionType1Map& theMap = BaseNS::getCallbackFunctionType1Map();
BaseNS::CallbackFunctionType1Map::iterator iter = theMap.find(my_base.get_N());
if ( iter != theMap.end() )
{
iter->second(my_base);
}
}
// Derived.hpp
// #pragma once
template <std::size_t N>
class Derived: public Base
{
public:
double some_other_value;
// Some functions and variables, for which
// the types and actions depend on N
const size_t get_N() override
{
return N;
}
Derived(double value1, double value2): Base(value1), some_other_value {value2} {};
};
// Derived.cpp
// Register call back functions for Derived.
namespace DerivedNS
{
template <std::size_t N>
void call_by_derived(Derived<N>& derived)
{
std::cout << "In call_by_derived<" << N << ">" << std::endl;
// Use derived.
}
template <std::size_t N>
void call_for_derived(Base& my_base)
{
Derived<N>* d_ptr = dynamic_cast<Derived<N>*>(&my_base);
if ( d_ptr != nullptr )
{
call_by_derived(*d_ptr);
}
else
{
// Error.
}
}
bool registerCallbackFunctions()
{
// Register callbacks for as many values of N as needed.
Base::registerCallback(1, call_for_derived<1>);
Base::registerCallback(2, call_for_derived<2>);
Base::registerCallback(3, call_for_derived<3>);
Base::registerCallback(4, call_for_derived<4>);
Base::registerCallback(5, call_for_derived<5>);
return true;
}
bool dummy = registerCallbackFunctions();
}
int main()
{
Derived<1> d1(0, 0);
Derived<2> d2(0, 0);
Derived<10> d3(0, 0);
call_by_base(d1);
call_by_base(d2);
call_by_base(d3); // Does not go to call_by_derived.
}
Output:
In call_by_base
In call_by_derived<1>
In call_by_base
In call_by_derived<2>
In call_by_base
I have this code:
// signal supporter parent
class signalable {};
template <class typeT = signalable>
typedef void (typeT::*trig)(std::string);
template <class typeT = signalable>
class trigger
{
private:
typeT* instance;
typeT::trig fun;
public:
trigger(typeT* inst, typeT::trig function)
: instance(inst), fun(function)
{}
void operator ()(std::string param)
{
(instance->*fun)(param);
}
};
And I get lots of compile error that I bet pros know of. I'm just confused a little bit about this context.
What I want to do is clear: Pass pointer to an object, and pointer to one of it's member functions, to make a functor and pass it over in my program.
Would appreciate your helps and "corrections".
Thank you!
Are you trying to do something like this?
#include <string>
#include <iostream>
// signal supporter parent
class signalable
{
public:
void foo(std::string s) { std::cout << "hello: " << s << std::endl; }
};
template <class typeT = signalable>
class trigger
{
typedef void (typeT::*trig)(std::string);
private:
typeT* instance;
trig fun;
public:
trigger(typeT* inst, trig function)
: instance(inst), fun(function)
{}
void operator ()(std::string param)
{
(instance->*fun)(param);
}
};
int main()
{
signalable s;
trigger<> t(&s, &signalable::foo);
t("world");
}
As for some of the more specific errors in your code, most of them seem to relate to your typedef. C++11 allows "template typedefs", but they don't look like that. Have a look at this thread for an example of template typedefs:
C++ template typedef
I have a container class, we'll call it
template <class T> CVector { ... }
I want to do something different with this class when T is a pointer type, e.g. something along the lines of:
template <class T*> CVector< SomeWrapperClass<T> >;
where SomeWrapperClass is expecting the type of the pointed to thing as its parameter. Unfortunately, this syntax doesn't quite work and with some digging, I haven't found a good way to get something like this working.
Why do it this way? I want to change, in a very large app, how some of our containers work when the type they're specialized on is a pointer vs. not a pointer - and ideally, i'd like to do it without changing the ~1,000 places in the code where there are things like CVector<Object*> vs CVector<int> or some such - and playing games with partial specializations seemed to be the way to go.
Am I on crack here?
If I understand you correctly, this might do what you want:
template<typename T>
class CVector { ... };
template<typename T>
class CVector<T*> : public CVector< SomeWrapperClass<T> > {
public:
// for all constructors:
CVector(...) : CVector< SomeWrapperClass<T> >(...) {
}
};
It adds an additional layer of inheritance to trick CVector<T*> into being a CVector< SomeWrapperClass<T> >. This might also be useful in case you need to add additional methods to ensure full compatibility between the expected interface for T* and the provided interface for SomeWrapperClass<T>.
This works just fine in C++...
#include <iostream>
template <class T>
class CVector
{
public:
void test() { std::cout << "Not wrapped!\n"; }
};
template <class T>
class CVector<T*>
{
public:
void test() { std::cout << "Wrapped!\n"; }
};
int main()
{
CVector<int> i;
CVector<double> d;
CVector<int*> pi;
CVector<double*> pd;
i.test();
d.test();
pi.test();
pd.test();
}
I don't think you can specialize a class using the syntax you describe... I don't know how that could possibly work. What you can do is specialize the class for pointers and re-implement its guts using the wrapper class around the raw pointers. I'm not sure if it will help, but this article describes specializing templates for pointers.
The Boost type traits library can help you achieve this. Check out the is_pointer type trait.
#include <boost/type_traits.hpp>
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class CVector {
public:
void addValue(const T& t) {
values_.push_back(t);
}
void print() {
typedef boost::integral_constant<bool,
::boost::is_pointer<T>::value> truth_type;
for (unsigned int i = 0; i < values_.size(); i++)
doPrint(values_[i], truth_type());
}
private:
void doPrint(const T& t, const boost::false_type&) {
cout << "Not pointer. Value:" << t << endl;
}
void doPrint(const T& t, const boost::true_type&) {
cout << "Pointer. Value: " << *t << endl;
}
std::vector<T> values_;
};
int main() {
CVector<int> integers;
integers.addValue(3);
integers.addValue(5);
integers.print();
CVector<int*> pointers;
int three = 3;
int five = 5;
pointers.addValue(&three);
pointers.addValue(&five);
pointers.print();
}
I don't think templates are quite that flexible.
A very brute force approach would be to specialize for all of your pointer types...which defeats the problem of using templates.
Could you have a different CVector class that is used only for vectors of pointers?
I agree with rlbond's answer. I have modified it a little bit to suit your need. CVector can be a derived class of the CVector itself. You can then use different members and functions for it.
#include <iostream>
#include <string>
template <class T>
class CVector
{
public:
void test() { std::cout << "Not wrapped!\n"; }
void testParent() { std::cout << "Parent Called\n";}
};
template <class T>
class CVector<T*>:
public CVector<T>
{
public:
void test(std::string msg) { std::cout << msg; testParent(); }
};
int main()
{
CVector<int> i;
CVector<double> d;
CVector<int*> pi;
CVector<double*> pd;
i.test();
d.test();
pi.test("Hello\n");
pd.test("World\n");
system("pause");
}