I have used templates to implement path policies.
#include <fstream>
#include <DefaultPolicy.h>
template<typename PathPolicy = DefaultPolicy>
class FileReader
{
public:
double getNextNumber();
private:
PathPolicy pp;
readNumbers() { std::ifstream myFile(pp.path); }; //And so on
};
I implemented:
[HEADER]
struct DefaultPolicy
{
public:
std::string path
DefaultPolicy()
} ;
[IMPLEMENTATION]
DefaultPolicy::DefaultPolicy() : path("."){}
So now I want to implement lots of different policies like:
[HEADER]
struct UnitTestPolicy
{
public:
std::string path
UnitTestPolicy()
} ;
[IMPLEMENTATION]
UnitTestPolicy::UnitTestPolicy() : path("unittests/resources"){}
[HEADER]
struct OperationalPathPolicy
{
public:
std::string path
OperationalPathPolicy()
} ;
[IMPLEMENTATION]
OperationalPathPolicy::OperationalPathPolicy() : path("/sw/cm/resources"){}
I'm not sure how to switch my policies. These are compile-time choices, and I can select the target that I'm building for, but the only idea I have is fall back to macros to make a selection. If I do that, then I don't really need the template abstraction for the policy.
How should I select a policy class at build time?
but the only idea I have is fall back to macros to make a selection
True.
If I do that, then I don't really need the template abstraction for the policy.
False. The template abstraction helps you to minimize use of the preprocessor and isolate your policies cleanly.
You can also force instantiation of your template class in a .cpp file to avoid compile-time overhead caused by templates, as you are aware of all the possible policy types.
// filereaderimpl.hpp
namespace detail
{
template<typename PathPolicy>
class FileReaderImpl { /* ... */ };
}
// filereader.hpp
#include <fileheaderimpl.hpp>
#ifdef SOME_BUILD_TIME_CHOICE
using FileReader = detail::FileHeaderImpl<SomePolicy>;
#else
using FileReader = detail::FileHeaderImpl<SomeOtherPolicy>;
#endif
EDIT: I misread the problem, the solution below will allow policy selection at runtime, you asked for selection at build time.
I think your problem would be better served by inheritance.
So you have a base PathPolicy (you can call it whatever i.e. DefaultPolicy) class and then have other policies inherit from the PathPolicy class.
So your UnitTestPolicy becomes
struct UnitTestPolicy : public PathPolicy
{
public:
UnitTestPolicy()
{
path = "blah//blah";
}
} ;
Then in your file reader, use the base class only to abstract other implementations of the policy class. That way your file reader doesn't care what the policy is; it's just going to read the file.
Working example here.
Related
In the hello world example of policy based design from wikipedia we use a common interface HelloWorld and configure it with different policies through templates - so far so good:
int main() {
// Example 1
typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyEnglish>
HelloWorldEnglish;
HelloWorldEnglish hello_world;
hello_world.Run(); // Prints "Hello, World!".
// Example 2
// Does the same, but uses another language policy.
typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyGerman>
HelloWorldGerman;
HelloWorldGerman hello_world2;
hello_world2.Run(); // Prints "Hallo Welt!".
}
This is all very nice and elegant, but what is the idiomatic way of managing / storing a collection of such configurable objects? For example, one would like to write
std::vector< some_magic_type > seasons_greetings; // What is the common type specifying the public interface only?
seasons_greetings.push_back(hello_world); // which is of type HelloWorldEnglish
seasons_greetings.push_back(hello_world2); // which is of type HelloWorldGerman
for (greeting : seasons_greetings) {
greeting.Run() // access only the public interface
}
In designing interfaces as base classes and deriving specialised implementations from them, I don't have this problem - I can always store pointers to the base class type - but I need to spell out all implementations leading to a whole lot of derived classes.
Policy Based Design promised to alleviate the explosion of derived classes that comes with this by using templates to mix and match behavior. But I pay for this with a whole lot of different types.
There must be an idiomatic way to deal with this. Any insight is greatly appreciated.
P.S.
I admit that I did not buy the book, but you might have guessed already.
This answer suggests storing a collection implies an inheritance based design, but does it really?
If you want to stay with unrelated classes you can use std:variant in combination with std::visit.
Example ( simply extend the main function from the original example )
using Variant = std::variant< HelloWorld<OutputPolicyWriteToCout, LanguagePolicyEnglish>, HelloWorld<OutputPolicyWriteToCout, LanguagePolicyGerman> >;
std::vector< Variant > seasons_greetings;
seasons_greetings.push_back(hello_world);
seasons_greetings.push_back(hello_world2);
for (auto& greeting : seasons_greetings) {
std::visit( [](auto& what){ what.Run(); }, greeting );
}
The bad side: You have to know all possible combinations of policies which can be really uncomfortable. But you can use some meta template stuff to create all variant types by giving type lists for each used policy and the template will generate all combinations, which is not such a big hack.
So here is a solution I found after pondering the comments again - key seems to combine the best of both worlds, polymorphism and policies - who would have thought ....
By introducing a common base class that defines only the public interface of the behavior class and then deriving the behavior class from that and the policies, I can get exactly what I want:
class HelloWorldInterface {
public:
// Behavior method.
void Run() const {
run();
}
private:
virtual void run() const = 0;
};
template <typename OutputPolicy, typename LanguagePolicy>
class HelloWorld : public HelloWorldInterface, private OutputPolicy, private LanguagePolicy {
private:
using OutputPolicy::Print;
using LanguagePolicy::Message;
void run() const override final {
Print(Message());
}
};
Then, I can write basically what I wanted from the beginning:
int main() {
// Example 1
using HelloWorldEnglish = HelloWorld<OutputPolicyWriteToCout, LanguagePolicyEnglish>;
// Example 2
// Does the same, but uses another language policy.
using HelloWorldGerman = HelloWorld<OutputPolicyWriteToCout, LanguagePolicyGerman>;
HelloWorldEnglish hello_world;
HelloWorldGerman hello_world2;
std::vector<const HelloWorldInterface*> greetings{&hello_world, &hello_world2};
for (auto x : greetings) {
x -> Run();
}
}
This way, one gets a single public interface that exposes behaviours resulting from an arbitrary combination of policies. Looks trivial now, though.
I am experimenting with the Builder/Fluent style of creating objects trying to extend some ideas presented in a course. One element I immediately didn't like with my test implementation was the large number of additional header files the client needs to include for the process to work, particularly when I wish to make use of public/private headers via the pImpl idiom for purposes of providing a library interface. I'm not entirely certain whether the problem lies with my implementation or I'm just missing an obvious 'last step' to achieve what I want.
The general gist is as follows (using the toy example of Pilots):
Firstly the client code itself:
(Note: for brevity, various boilerplate and irrelevant code has been omitted)
Pilot p = Pilot::create()
.works().atAirline("Sun Air").withRank("Captain")
.lives().atAddress("123 Street").inCity("London")
What's happening here is:
In Pilot.h, the Pilot class is defined with a static member method called create() that returns an instance of a PilotBuilder class defined in PilotBuilder.h and forward declared in Pilot.h
Essentially the PilotBuilder class is a convenience builder only used to present builders of the two different facets of a Pilot (.works() and .lives()), letting you switch from one builder to another.
Pilot.h:
class PilotBuilder;
class Pilot {
private:
// Professional
string airline_name_, rank_;
// Personal
string street_address_, city_;
Pilot(){}
public:
Pilot(Pilot&& other) noexcept;
static PilotBuilder create();
friend class PilotBuilder;
friend class PilotProfessionalBuilder;
friend class PilotPersonalBuilder;
};
Pilot.cpp:
#include "PilotBuilder.h"
PilotBuilder Pilot::create() {
return PilotBuilder();
}
// Other definitions etc
PilotBuilder.h
#include "public/includes/path/Pilot.h"
class PilotProfessionalBuilder;
class PilotPersonalBuilder;
class PilotBuilder {
private:
Pilot p;
protected:
Pilot& pilot_;
explicit PilotBuilder(Pilot& pilot) : pilot_{pilot} {};
public:
PilotBuilder() : pilot_{p} {}
operator Pilot() {
return std::move(pilot_);
}
PilotProfessionalBuilder works();
PilotPersonalBuilder lives();
};
PilotBuilder.cpp
#include "PilotBuilder.h"
#include "PilotProfessionalBuilder.h"
#include "PilotPersonalBuilder.h"
PilotPersonalBuilder PilotBuilder::lives() {
return PilotPersonalBuilder{pilot_};
}
PilotProfessionalBuilder PilotBuilder::works() {
return PilotProfessionalBuilder{pilot_};
}
As you can imagine the PilotProfessionalBuilder class and the PilotPersonalBuilder class simply implement the methods relevant to that particular facet eg(.atAirline()) in the fluent style using the reference provided by the PilotBuilder class, and their implementation isn't relevant to my query.
Avoiding the slightly contentious issue of providing references to private members, my dilemma is that to make use of my pattern as it stands, the client has to look like this:
#include "public/includes/path/Pilot.h"
#include "private/includes/path/PilotBuilder.h"
#include "private/includes/path/PilotProfessionalBuilder.h"
#include "private/includes/path/PilotPersonalBuilder.h"
int main() {
Pilot p = Pilot::create()
.works().atAirline("Sun Air").withRank("Captain")
.lives().atAddress("123 Street").inCity("London");
}
What I cannot figure out is:
How do I reorder or reimplement the code so that I can simply use #include "public/includes/path/Pilot.h" in the client, imagining say, that I'm linking against a Pilots library where the rest of the implementation resides and still keep the same behaviour?
Provided someone can enlighten me on point 1., is there any way it would be then possible to move the private members of Pilot into a unique_ptr<Impl> pImpl and still keep hold of the static create() method? - because the following is obviously not allowed:
:
PilotBuilder Pilot::create() {
pImpl = make_unique(Impl); /* struct containing private members */
return PilotBuilder();
}
Finally, I am by no means an expert at any of this so if any of my terminology is incorrect or coding practices really need fixing I will gladly receive any advice people have to give. Thank you!
I have made a big edit in attempt to clarify what help I am asking for and to try to make the question appropriate for Stack Overflow.
The problem in general: I have an existing library class which allows me to query a server for information. That library class is widely used by a large amount of legacy software, so I am somewhat limited in the changes I can make to it. Likewise, reimplementing it in a better fashion might not be time well spent.
The problem in specific: I've create a simplified "toy" model of my approach below with 3 classes. The real thing is more complex, as there are polymorphic variations, more functionality, error handling, etc.
In "toy" model code included below, Gateway is the existing library class. I've tried to show how I would like to use it, with a result set and a way to access each member of the set. The idea is similar to how a well-implemented database API might look, with a statement, result and row -- except in my case, what would be the statement class is hobbled by a poor design which includes part of the result functionality.
The toy example below will not compile as-is because of the following cyclical dependecy. The Gateway class includes the ResultSet class and depends upon it, as it returns a ResultSet object. The ResultSet class depends on the Member class, as it uses it to convert the data returned from the server into primitives (e.g. string). But the Member class refers back to the Gateway class to access that data, and so there is a cycle.
I want to find a solution which will provide the ResultSet and Member functionality.
For a simpler 2 class problem, I know a solution. It is to create a superclass that one class derives from (is-a), and which the other class is composed of (has-a), such that both original classes depend on the third, and all is right with the world. :-)
For my 3 class problem, for some reason I have been unable to wrap my head around how to refactor it to make it work.
// Gateway.h
#include "ResultSet.h"
class Gateway {
ResultSet exec(string params);
};
// Gateway.cpp
ResultSet Gateway::exec(string p) { ... }
// ResultSet.h
#include "Member.h"
class ResultSet {
ResultSet(); // ctor
int index;
bool next();
string getCurrent(Member member);
};
// ResultSet.cpp
ResultSet::ResultSet() { index = 0; }
bool ResultSet::next() { ++index < length; }
string ResultSet::getCurrent(Member member) { member.fetch(index) }
// Member.h
#include "Gateway.h"
class Member {
Gateway gateway;
string fetch(int i);
};
// Member.cpp
string Member::fetch(int i) { return gateway.sGet(i); }
// Example desired usage of the final API.
main() {
Gateway gate;
ResultSet set;
Member member;
set = gate.exec("...");
while (set.next()) {
cout << set.getCurrent(member) << endl;
}
}
The solution to your issue is to forward declare the overlapping classes in the header files, and then to include their actual .h files from your .cpp implementation files.
For instance, to get around Gateway's dependencies on ResultSet,
// Gateway.h
class ResultSet;
class Gateway {
ResultSet exec(string params);
};
This forward declares the class ResultSet.
Now in Gateway.cpp, we have to provide the actual interface to the compiler. So now we include ResultSet.h.
// Gateway.cpp
#include "ResultSet.h"
ResultSet Gateway::exec(string p) { ... }
We do this for your other cyclic relationships, and you will then have source you can compile and build.
For ResultSet, we will forward declare Member.
// ResultSet.h
class Member;
class ResultSet {
ResultSet(); // ctor
int index;
bool next();
string getCurrent(Member member);
};
And in its implementation file, we will finally include Member's header.
// ResultSet.cpp
#include "Member.h"
ResultSet::ResultSet() { index = 0; }
bool ResultSet::next() { ++index < length; }
string ResultSet::getCurrent(Member member) { member.fetch(index) }
And finally, Member...
// Member.h
class Gateway;
class Member {
Gateway gateway;
string fetch(int i);
};
And of course, Member.cpp must then include Gateway's information.
// Member.cpp
#include "Gateway.h"
string Member::fetch(int i) { return gateway.sGet(i); }
Now there are no cyclic dependencies.
I have written a library (doesn't matter what it does), which obviously has its header file. Now, I want to hide private elements of that header file, so if I provide my library to somebody, he/she should only see public members (preferably no class definition, nothing other than function definitions). One way would be creating C-style header, which will contain some kind of "init" method which will be used to create an instance of the actual class of library and the user will have to pass a pointer of that object to every function to do the job.
Is it a good practice?
Are there any other publicly accepted ways of doing something like that?
Thanks in advance.
In addition to the Factory pattern (which, in my opinion, can become unwieldy), you can also hide your private members behind a PIMPL (Pointer to IMPLementation):
// Interface.hpp
class Implementation;
class Interface {
public:
Interface() : pimpl(new Implementation()) {}
void publicMethod();
private:
std::unique_ptr<Implementation> pimpl;
};
// Interface.cpp
class Implementation {
public:
void PrivateMember();
};
void Interface::publicMethod() { pimpl->PrivateMember(); }
This has the advantage of hiding implementation, at the cost of a single pointer indirection, not much different from the typical inheritance-based Factory pattern.
This can also be ABI stable. Changes to your implementation won't affect linkage, since no changes will ever be visible to the rest of the program. This is a good pattern to use when implementing shared objects, for example.
It's also a common C++ idiom, so other C++ programmers will recognize it without question.
In the case of a class which will follow the Singleton pattern, you can avoid exposing the PIMPL at all, and simply write the entire implementation in an anonymous namespace in your .cpp file, where you can put as much state and private functions as you wish, without even hinting at it in your interface.
You can create a publicly-visible interface. Create an abstract class with the functions you want to expose, then have your implementation extend it.
For example, an interface:
class Interface {
public:
virtual void publicMethod() = 0;
...
};
And the implementation:
class Implementation : Interface {
public:
virtual void publicMethod();
private:
int hiddenMethod();
};
Then you only export the symbols for Interface. Now, in order for the user of the library to get instances of Interface which are actually Implementations, you need to provide a factory:
class Factory {
public:
//can create and return an Implementation pointer, but caller will get an Interface pointer
std::shared_ptr<Interface> getImplementationInstance();
}
Base on Eric Finn's answer, you can just declare an interface class to hold all your public methods which considered to be your API, and hide all implementations and private members/methods in implementation class which inherits interface class, here's the example:
Your header file: my_api.h
// your API in header file
// my_api.h
class interface {
public:
static interface* CreateInstance();
virtual void draw() = 0;
virtual void set(int) = 0;
};
your implementation(shared library): my_api.cpp (users won't see this when you make it a shared library)
So you can hide all your implementation and private methods/members here
#include "my_api.h"
// implementation -> in .cc file
class implementation : public interface {
int private_int_;
void ReportValue_();
public:
implementation();
void draw();
void set(int new_int);
};
implementation::implementation() {
// your actual constructor goes here
}
void implementation::draw() {
cout << "Implementation class draws something" << endl;
ReportValue_();
}
void implementation::ReportValue_() {
cout << "Private value is: " << private_int_ << endl;
}
void implementation::set(int new_int) {
private_int_ = new_int;
}
interface* interface::CreateInstance() {
return new implementation;
}
How user uses your API:
#include <iostream>
#include "my_api.h"
int main(int argc, const char * argv[])
{
using namespace std;
interface* a; interface* b;
a = interface::CreateInstance();
a->set(1);
b = interface::CreateInstance();
b->set(2);
b->draw();
a->draw();
return 0;
}
Output:
Implementation class draws
Private int is: 2
Implementation class draws
Private int is: 1
In this pattern, your api is just an abstract class which works like a factory, you can also implement the virtual method in different classes and specify which instance you would like to call.
I think you need to create Dynamic Link Library (dll).
Please take a quick look at this link:
You might want to take a look at the envelope/letter idiom, bridge design pattern, or proxy pattern. Basically, you would create an outer (public) class that would just forward your public method calls to the inner (private) class. Your InnerClass.h header only needs to be visible/known to your OuterClass.cpp and InnerClass.cpp source files.
Each of these patterns provides a mechanism of separating the implementation from the interface so that the caller is not coupled to the implementation. Sometimes this is desired to reduce compiler dependencies on large C++ projects. Another common reason for wanting to do this is just when you want to hide the implementation details so that the caller only sees a single opaque pointer.
======= OuterClass.h =====
class InnerClass; // forward declaration is all that's needed
class OuterClass {
private:
InnerClass *pInner;
public:
InnerClass();
bool doSomething();
};
======= OuterClass.cpp ======
#include "OuterClass.h"
#include "InnerClass.h"
OuterClass::OuterClass() :
pInner(new InnerClass())
{
}
bool OuterClass::doSomething()
{
return pInner->doSomething();
}
There actually is a way to do this without having to use classes. I had the same issue and here is a very simple solution:
Just put your private things into the .cpp file. Your header file will look something like this:
// These will be visible to everyone using this library
void function();
int someNumber = 2;
and your .cpp file:
void function() {
// whatever this function does
}
// This will be only visible to the library itself
static void secretFunction() {
doSomeSecretStuff;
}
static int PIN = 1234;
// Okay, if you write this Number into your library and expect it to be safe,
// then screw you, but at least no one will be able to access it with code
When calling the "public" functions from outside you now don't need any instance of that class anymore: Just place the library in the correct directory and include it, but you probably have already taken care of that) and call the functions by their names in the Lib.h file. In the instance of this example it would look something like this:
#include "Lib.h"
int main(int argc, const char * argv[]) {
function();
return 0;
}
Thanks to Edgar Bonet for helping me find this solution on the Arduino Stackexchange!
I'm facing problems with the design of a C++ library of mine. It is a library for reading streams that support a feature I haven't found on other "stream" implementations. It is not really important why I've decided to start writing it. The point is I have a stream class that provides two important behaviours through multiple inheritance: shareability and seekability.
Shareable streams are those that have a shareBlock(size_t length) method that returns a new stream that shares resources with its parent stream (e.g. using the same memory block used by parent stream). Seekable streams are those that are.. well, seekable. Through a method seek(), these classes can seek to a given point in the stream. Not all streams of the library are shareable and/or seekable.
A stream class that both provides implementation for seeking and sharing resources inherits interface classes called Seekable and Shareable. That's all good if I know the type of such a stream, but, sometimes, I might want a function to accept as argument a stream that simply fulfills the quality of being seekable and shareable at the same time, regardless of which stream class it actually is. I could do that creating yet another class that inherits both Seekable and Shareable and taking a reference to that type, but then I would have to make my classes that are both seekable and shareable inherit from that class. If more "behavioural classes" like those were to be added, I would need to make several modifications everywhere in the code, soon leading to unmaintainable code. Is there a way to solve this dilemma? If not, then I'm absolutely coming to understand why people are not satisfied by multiple inheritance. It almost does the job, but, just then, it doesn't :D
Any help is appreciated.
-- 2nd edit, preferred problem resolution --
At first I thought Managu's solution would be my preferred one. However, Matthieu M. came with another I preferred over Managu's: to use boost::enable_if<>. I would like to use Managu's solution if BOOST_MPL_ASSERT produced messages weren't so creepy. If there was any way to create instructive compile-time error messages, I would surely do that way. But, as I said, the methods available produce creepy messages. So I prefer the (much) lesser instructive, yet cleaner message produced when boost::enable_if<> conditions are not met.
I've created some macros to ease the task to write template functions that take arguments inheriting select class types, here they go:
// SonettoEnableIfDerivedMacros.h
#ifndef SONETTO_ENABLEIFDERIVEDMACROS_H
#define SONETTO_ENABLEIFDERIVEDMACROS_H
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/array/elem.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/utility/enable_if.hpp>
/*
For each (TemplateArgument,DerivedClassType) preprocessor tuple,
expand: `boost::is_base_and_derived<DerivedClassType,TemplateArgument>,'
*/
#define SONETTO_ENABLE_IF_DERIVED_EXPAND_CONDITION(z,n,data) \
boost::is_base_and_derived<BOOST_PP_TUPLE_ELEM(2,1,BOOST_PP_ARRAY_ELEM(n,data)), \
BOOST_PP_TUPLE_ELEM(2,0,BOOST_PP_ARRAY_ELEM(n,data))>,
/*
ReturnType: Return type of the function
DerivationsArray: Boost.Preprocessor array containing tuples in the form
(TemplateArgument,DerivedClassType) (see
SONETTO_ENABLE_IF_DERIVED_EXPAND_CONDITION)
Expands:
typename boost::enable_if<
boost::mpl::and_<
boost::is_base_and_derived<DerivedClassType,TemplateArgument>,
...
boost::mpl::bool_<true> // Used to nullify trailing comma
>, ReturnType>::type
*/
#define SONETTO_ENABLE_IF_DERIVED(ReturnType,DerivationsArray) \
typename boost::enable_if< \
boost::mpl::and_< \
BOOST_PP_REPEAT(BOOST_PP_ARRAY_SIZE(DerivationsArray), \
SONETTO_ENABLE_IF_DERIVED_EXPAND_CONDITION,DerivationsArray) \
boost::mpl::bool_<true> \
>, ReturnType>::type
#endif
// main.cpp: Usage example
#include <iostream>
#include "SonettoEnableIfDerivedMacros.h"
class BehaviourA
{
public:
void behaveLikeA() const { std::cout << "behaveLikeA()\n"; }
};
class BehaviourB
{
public:
void behaveLikeB() const { std::cout << "behaveLikeB()\n"; }
};
class BehaviourC
{
public:
void behaveLikeC() const { std::cout << "behaveLikeC()\n"; }
};
class CompoundBehaviourAB : public BehaviourA, public BehaviourB {};
class CompoundBehaviourAC : public BehaviourA, public BehaviourC {};
class SingleBehaviourA : public BehaviourA {};
template <class MustBeAB>
SONETTO_ENABLE_IF_DERIVED(void,(2,((MustBeAB,BehaviourA),(MustBeAB,BehaviourB))))
myFunction(MustBeAB &ab)
{
ab.behaveLikeA();
ab.behaveLikeB();
}
int main()
{
CompoundBehaviourAB ab;
CompoundBehaviourAC ac;
SingleBehaviourA a;
myFunction(ab); // Ok, prints `behaveLikeA()' and `behaveLikeB()'
myFunction(ac); // Fails with `error: no matching function for
// call to `myFunction(CompoundBehaviourAC&)''
myFunction(a); // Fails with `error: no matching function for
// call to `myFunction(SingleBehaviourA&)''
}
As you can see, the error messages are exceptionally clean (at least in GCC 3.4.5). But they can be misleading. It doesn't inform you that you've passed the wrong argument type. It informs you that the function doesn't exist (and, in fact, it doesn't due to SFINAE; but that may not be exactly clear to the user). Still, I prefer those clean messages over those randomStuff ... ************** garbage ************** BOOST_MPL_ASSERT produces.
If you find any bugs in this code, please edit and correct them, or post a comment in that regard. The one major issue I find in those macros is that they're limited to some Boost.Preprocessor limits. Here, for example, I can only pass a DerivationsArray of up to 4 items to SONETTO_ENABLE_IF_DERIVED(). I think those limits are configurable though, and maybe they will even be lifted in upcoming C++1x standard, won't they? Please, correct me if I'm wrong. I don't remember if they have suggested changes to the preprocessor.
Thank you.
Just a few thoughts:
STL has this same sort of problem with iterators and functors. The solution there was basically to remove types from the equation all together, document the requirements (as "concepts"), and use what amounts to duck typing. This fits well a policy of compile-time polymorphism.
Perhaps a midground would be to create a template function which statically checks its conditions at instantiation. Here's a sketch (which I don't guarantee will compile).
class shareable {...};
class seekable {...};
template <typename StreamType>
void needs_sharable_and_seekable(const StreamType& stream)
{
BOOST_STATIC_ASSERT(boost::is_base_and_derived<shareable, StreamType>::value);
BOOST_STATIC_ASSERT(boost::is_base_and_derived<seekable, StreamType>::value);
....
}
Edit: Spent a few minutes making sure things compiled, and "cleaning up" the error messages:
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/mpl/assert.hpp>
class shareable {};
class seekable {};
class both : public shareable, public seekable
{
};
template <typename StreamType>
void dosomething(const StreamType& dummy)
{
BOOST_MPL_ASSERT_MSG((boost::is_base_and_derived<shareable, StreamType>::value),
dosomething_requires_shareable_stream,
(StreamType));
BOOST_MPL_ASSERT_MSG((boost::is_base_and_derived<seekable, StreamType>::value),
dosomething_requires_seekable_stream,
(StreamType));
}
int main()
{
both b;
shareable s1;
seekable s2;
dosomething(b);
dosomething(s1);
dosomething(s2);
}
Take a look at boost::enable_if
// Before
template <class Stream>
some_type some_function(const Stream& c);
// After
template <class Stream>
boost::enable_if<
boost::mpl::and_<
boost::is_base_and_derived<Shareable,Stream>,
boost::is_base_and_derived<Seekable,Stream>
>,
some_type
>
some_function(const Stream& c);
Thanks to SFINAE this function will only be considered if Stream satisfies the requirement, ie here derive from both Shareable and Seekable.
How about using a template method?
template <typename STREAM>
void doSomething(STREAM &stream)
{
stream.share();
stream.seek(...);
}
You might want the Decorator pattern.
Assuming both Seekable and Shareable have common ancestor, one way I can think of is trying to downcast (of course, asserts replaced with your error-checking):
void foo(Stream *s) {
assert(s != NULL);
assert(dynamic_cast<Seekable*>(s) != NULL);
assert(dynamic_cast<Shareable*>(s) != NULL);
}
Replace 'shareable' and 'seekable' with 'in' and 'out' and find your 'io' solution. In a library similar problems should have similar solutions.