Multiply inheriting from function objects with a common base (C++) - c++

I have a few function objects that have no member variables. The function objects are very simple in nature. They all inherit from unary_function<> or binary_function<>. For example, a couple of the function objects may be something like this:
struct key_to_hash_method_1 : public binary_function<int, int, int>
{
int operator() (int a, int b) const { /* do something */ }
};
template <typename key_to_hash_method>
struct hash_shrink_method_1 : public binary_function<int, int, int>, public key_to_hash_method
{
int operator() (int a, int b) const { /* do something while utilizing key_to_hash_method */ }
};
/* and more variations of these function objects */
A template class uses these function objects by taking them as template parameters as policies. The template class then inherits from them:
template <typename hash_method>
class foo : public hash_method
{
public:
/* do something while using hash_method as well as using the information provided by binary_function<> to selective compile different functions*/
};
Of course, in the interest of keeping the example simple, the above may not make much sense as far as usefulness goes.
Why am I inheriting instead of using composition? Simply to avoid the empty classes from taking up space. Whether the space saved is minuscule or not is not the point of the question.
As you can see from the above code, binary_function<int, int, int> will be inherited twice, which gives rise to the warning (in VC++ 2008):
Warning 1 warning C4584: 'hash_shrink_method_1<key_to_hash_method>' : base-class 'std::binary_function<_Arg1,_Arg2,_Result>' is already a base-class of 'key_to_hash_method_1' c:\visual studio 2008\projects\defaulttemplatearguments\main.cpp 12
Now generally, in multiple inheritance, this is solved by virtual inheritance; which I want to avoid in this case. What can I do in this situation to remove the warning?
My immediate solution is to not inherit from binary_function<> since I am assuming that key_to_hash_method will be a binary_function. This solution feels a bit like a programmer who does not have access to include guards or pragma once statement. Yes, he can avoid including the header twice, but he'd rather the compiler figure it out for him. I would like the same in this case.
Example code, if you want to try it out:
#include <functional>
using namespace std;
struct key_to_hash_method_1 : public binary_function<int, int, int>
{
int operator() (int a, int b) const { return a + b; }
};
template <typename key_to_hash_method>
struct hash_shrink_method_1 : public binary_function<int, int, int>, public key_to_hash_method
{
int operator() (int a, int b) const { return key_to_hash_method::operator()(1, 2) * 5; }
};
template <typename hash_method>
class foo : public hash_method
{
public:
int test()
{
/* in actual code, this function selectively calls other functions
depending on whether hash_method is unary or binary */
return hash_method::operator()(5, 6);
}
};
int main()
{
foo<hash_shrink_method_1<key_to_hash_method_1> > f;
printf("%i\n", f.test());
}

Your hash_shrink_method_1 doesn't need to inherit from binary_function directly, since you assume that its parameter class key_to_hash_method already does so. You can add a static assertion (std::is_base_of) if you want to be sure; though if you already have C++11, you can do away with the obsolete binary_function anyway.

Language lawyering part.
GCC gives a better warning:
mi.C: In instantiation of ‘hash_shrink_method_1<key_to_hash_method_1>’:
mi.C:18: instantiated from ‘foo<hash_shrink_method_1<key_to_hash_method_1> >’
mi.C:30: instantiated from here
mi.C:12: warning: direct base ‘std::binary_function<int, int, int>’ inaccessible in ‘hash_shrink_method_1<key_to_hash_method_1>’ due to ambiguity
Which is to say, if you inherit from the same base both directly and indirectly, the direct base class cannot be accessed. An attempt to do so will be a compile-time error.
hash_shrink_method_1<key_to_hash_method_1> foo;
binary_function<int, int, int>& bar = foo; // error: ambiguous
There's no way to disambiguate that.
The obvious solution, apart from using virtual inheritance, would be introducing an intermediate layer of inheritance.
template <typename T>
struct wrapped : public T {};
and then
template <typename key_to_hash_method>
struct hash_shrink_method_1 : public wrapped < binary_function<int, int, int> >,
public wrapped <key_to_hash_method >
Now it is possible to disambiguate:
hash_shrink_method_1<key_to_hash_method_1> foo;
foo::wrapped<binary_function<int, int, int> >& intermediate = foo;
binary_function<int, int, int>& bar = intermediate;
OOP/OOD lawyering part.
Please note however that your class now has two operator()(int,int) functions publicly accessible. Which one will be selected depends on how do you access them.
foo<hash_shrink_method_1<key_to_hash_method_1> > f;
hash_shrink_method_1<key_to_hash_method_1>& ff = f;
cout << ff(5,6) << endl; // 15
key_to_hash_method_1& gg = ff;
cout << gg(5,6) << endl; // 11
If this is not what you want, you should not use public inheritance here or perhaps inheritance in general. There's no reason fot inheritance here.

I see two pretty nice approaches.
The first you already mentioned: composition. This is simple to do, and the code looks quite natural.
However, the way your examples run, it looks like your code shouldn't even need to instantiate any these function objects. So you could change the classes to have a static method which does the same thing as operator(), e.g.
struct key_to_hash_method_1 : public binary_function<int, int, int>
{
static int invoke (int a, int b) { return a + b; }
int operator() (int a, int b) const { return a + b; }
};
template <typename key_to_hash_method>
struct hash_shrink_method_1 : public binary_function<int, int, int>
{
static int invoke (int a, int b) { return key_to_hash_method::invoke(1, 2) * 5 }
int operator() (int a, int b) const { return key_to_hash_method::invoke(1, 2) * 5; }
};
Notice that hash_shrink_method_1 doesn't need to inherit from key_to_hash_method_1 any more. Similarly, foo won't need to inherit from hash_method.
(An alternative to using these static methods is to implement the singleton pattern)
A last thought occured to me: since you're using templates to invoke the methods, you don't really need to use binary_function (at least as far as these examples go). If your actual situation is similar to your example code, it might be an idea to just get rid of binary_function.

Related

Conditionally creating members inside a class

Is it possible to do something like:
template <unsigned majorVer, unsigned minorVer>
class Object
{
public:
if constexpr ((majorVer == 1) && (minorVer > 10))
bool newField;
else
int newInt
};
or
template <unsigned majorVer, unsigned minorVer>
class Object
{
public:
if constexpr ((majorVer == 1) && (minorVer > 10))
bool newField;
// Nothing other wise
};
using c++17?
I would like to change the structure of a class based on some condition that can be checked at compile time. Is there any way to achieve this?
You can't use if constexpr for this. You would have to collapse them into one member using something like std::conditional:
std::conditional_t<(majorVer == 1) && (minorVer > 10), bool, int> newField;
Alternatively, you can wrap each of the two kinds of the fields in their own type:
struct A { bool newField; };
struct B { int newInt; };
And either inherit from std::conditional_t<???, A, B> or have one of those as a member.
For the case where you want either a member or nothing, the other case just needs to be an empty type. In C++20, that's:
struct E { };
[[no_unique_address]] std::conditional_t<some_condition(), bool, E> newField;
In C++17 and earlier, you'll want to inherit from this to ensure that the empty base optimization kicks in:
struct B { bool field; };
struct E { };
template <unsigned majorVer, unsigned minorVer>
class Object : private std::conditional_t<some_condition(), B, E>
{ ... };
if-constexpr is about control flow, not about memory layout. Maybe the reflection TS could be a good fit for this. However, untill that is available, you'll need other techniques.
constexpr bool useLegacyInt(unsigned major, unsigned minor)
{
return (majorVer <= 1) && (minorVer <= 10));
}
template<bool>
class ObjectBase
{
book newField;
};
template<>
class ObjectBase<true>
{
int newInt;
};
template <unsigned majorVer, unsigned minorVer>
class Object : public ObjectBase<useLegacyInt (majorVer, minorVer)>
{};
Based on this, you could do some refinements. You don't only influence the members, also the methods. So also setters and getters ... could have a different signature. Protected helper functions could provide a bool API to Object to separate the implementation.
Finally, I would not recommend using a bool, I rather expect an enumeration as this can have multiple values.
Inheriting from an earlier version could also be possible if a new version only extends. And with some default template arguments, you can even do more fancy things.
Be warned, this kind of backwards compatibility could become complex really quickly. Sometimes it's better to just copy the complete code in a legacy version and keep it as is, without interference of the new API. This at the cost of duplicated code.

C++ Calling functions with different signatures, depending on type

I'm wondering what is a good design pattern is for the following scenario. Three questions:
1) I have a templated "Container" class for subclasses of "Derived". I want to be able to store different kinds of template objects (of either type A or B, both subclasses of Derived) in a vector. How to do this?
2) I have a template-specific function "func" that operates on Containers and has a variable number of arguments, depending on whether the template type of Container is A or B. What's a good way to check template types at runtime to call the appropriate function?
3) Do templates even make sense for this use case?
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
struct Derived {};
struct A : Derived {
int x;
A(int x) : x(x) {}
};
struct B : Derived {
bool y;
B(bool y) : y(y) {}
};
template <typename T>
struct Container
{
T item;
Container(T i) : item(i) {}
};
// definition of a template function for type a, with specialization
void func(Container<A> c, int a, int b) {
cout << "update for A called" << endl;
}
void func(Container<B> c, bool x) {
cout << "update for B called" << endl;
}
int main(int argc, char const *argv[])
{
Container<A> * foo = new Container<A>(A(1));
Container<B> * bar = new Container<B>(B(true));
// test that func() works
func(*foo,1,2);
func(*bar,false);
vector< Container<Derived>* > vec;
// this does not work
vec.push_back(unique_ptr< Container<Derived *> >(foo));
vec.push_back(unique_ptr< Container<Derived *> >(bar));
for (Container<Derived>* d : vec) {
// how to call the proper func(d)?
}
return 0;
}
1) You can store pointers to A (type A *) or pointers to B (type B *) in a std::vector<Derived *>, because Derived is a base for both A and B. It is not possible to store a Container<A> and a Container<B> into the same vector, because there is no inheritance relationship between them. This is also (indirectly) the reason that converting foo and bar to unique_ptr<Container<Derived *> > is being rejected by your compiler.
2) Your func() is not a "template specific function". It is not even a templated function. It is a function that is overloaded, with one variant that accepts two arguments, and one variant that accepts three.
3) Given that your code is invalid, it is not possible to infer what your use case is. Given that you are trying to convert objects to unrelated types, my guess is that your use case does not make sense in C++, let alone using templates for it.
Also, don't use Java (or whatever other language you are thinking in) techniques in C++, because they do not work the same way. Specifically;
Container<A> * foo = new Container<A>(A(1));
Container<B> * bar = new Container<B>(B(true));
func(*foo,1,2);
func(*bar,false);
is unnecessary. It is used in Java for various reasons that are invalid in C++, even if the code compiles. Instead, do this;
Container<A> foo A(1);
Container<B> bar B(true);
func(foo,1,2);
func(bar,false);
This is valid and safe C++ (and will not work in Java, but that's another story).

Allowing access to private members

This question is somewhat a continuation of this one I've posted.
What I was trying to do: my point was to allow access to private members of a base class A in a derived class B, with the following restraints:
what I want to access is a structure -- an std::map<>, actually --, not a method;
I cannot modified the base class;
base class A has no templated method I may overload as a backdoor alternative -- and I would not add such method, as it would be going against the second restraint.
As a possible solution, I have been pointed to litb's solution (post / blog), but, for the life of me, I haven't been able to reach an understanding on what is done in these posts, and, therefore, I could not derive a solution to my problem.
What I am trying to do: The following code, from litb's solution, presents an approach on how to access private members from a class/struct, and it happens to cover the restrictions I've mentioned.
So, I'm trying to rearrange this one code:
template<typename Tag, typename Tag::type M>
struct Rob {
friend typename Tag::type get(Tag) {
return M;
}
};
// use
struct A {
A(int a):a(a) { }
private:
int a;
};
// tag used to access A::a
struct A_f {
typedef int A::*type;
friend type get(A_f);
};
template struct Rob<A_f, &A::a>;
int main() {
A a(42);
std::cout << "proof: " << a.*get(A_f()) << std::endl;
}
To something that would allow me to do the following -- note I'm about to inherit the class, as the entries in the std::map<> are added right after the initialization of the derived class B, i.e., the std::map<> isn't simply a static member of class A with a default value, so I need to access it from a particular instance of B:
// NOT MY CODE -- library <a.h>
class A {
private:
std::map<int, int> A_map;
};
// MY CODE -- module "b.h"
# include <a.h>
class B : private A {
public:
inline void uncover() {
for (auto it(A_map.begin()); it != A_map.end(); ++it) {
std::cout << it->first << " - " << it->second << std::endl;
}
}
};
What I'd like as an answer: I'd really love to have the above code working -- after the appropriate modifications --, but I'd be very content with an explanation on what is done in the first code block -- the one from litb's solution.
The blog post and its code is unfortunately a bit unclear. The concept is simple: an explicit template instantiation gets a free backstage pass to any class, because
An explicit instantiation of a library class may be an implementation detail of a client class, and
Explicit instantiations may only be declared at namespace scope.
The natural way to distribute this backstage pass is as a pointer to member. If you have a pointer to a given class member, you can access it in any object of that class regardless of the access qualification. Fortunately, pointer-to-members can be compile-time constants even in C++03.
So, we want a class which generates a pointer to member when it's explicitly instantiated.
Explicit instantiation is just a way of defining a class. How can merely generating a class do something? There are two alternatives:
Define a friend function, which is not a member of the class. This is what litb does.
Define a static data member, which gets initialized at startup. This is my style.
I'll present my style first, then discuss its shortcoming, and then modify it to match litb's mechanism. The end result is still simpler than the code from the blog.
Simple version.
The class takes three template arguments: the type of the restricted member, its actual name, and a reference to a global variable to receive a pointer to it. The class schedules a static object to be initialized, whose constructor initializes the global.
template< typename type, type value, type & receiver >
class access_bypass {
static struct mover {
mover()
{ receiver = value; }
} m;
};
template< typename type, type value, type & receiver >
typename access_bypass< type, value, receiver >::mover
access_bypass< type, value, receiver >::m;
Usage:
type_of_private_member target::* backstage_pass;
template class access_bypass <
type_of_private_member target::*,
& target::member_name,
backstage_pass
>;
target t;
t.* backstage_pass = blah;
See it work.
Unfortunately, you can't rely on results from this being available for global-object constructors in other source files before the program enters main, because there's no standard way to tell the compiler which order to initialize files in. But globals are initialized in the order they're declared, so you can just put your bypasses at the top and you'll be fine as long as static object constructors don't make function calls into other files.
Robust version.
This borrows an element from litb's code by adding a tag structure and a friend function, but it's a minor modification and I think it remains pretty clear, not terribly worse than the above.
template< typename type, type value, typename tag >
class access_bypass {
friend type get( tag )
{ return value; }
};
Usage:
struct backstage_pass {}; // now this is a dummy structure, not an object!
type_of_private_member target::* get( backstage_pass ); // declare fn to call
// Explicitly instantiating the class generates the fn declared above.
template class access_bypass <
type_of_private_member target::*,
& target::member_name,
backstage_pass
>;
target t;
t.* get( backstage_pass() ) = blah;
See it work.
The main difference between this robust version and litb's blog post is that I've collected all the parameters into one place and made the tag structure empty. It's just a cleaner interface to the same mechanism. But you do have to declare the get function, which the blog code does automatically.
OK, so you asked about how to make that weird "Rob" code work with your use case, so here it is.
// the magic robber
template<typename Tag, typename Tag::type M>
struct Rob {
friend typename Tag::type get(Tag) {
return M;
}
};
// the class you can't modify
class A {
private:
std::map<int, int> A_map;
};
struct A_f {
typedef std::map<int, int> A::*type;
friend type get(A_f);
};
template struct Rob<A_f, &A::A_map>;
class B : private A {
public:
inline void uncover() {
std::map<int, int>::iterator it = (this->*get(A_f())).begin();
}
};
Now, I personally think the cure here may be worse than the disease, despite that I'm usually the last one you'll see claiming that abusing C++ is OK. You can decide for yourself, so I've posted this as a separate answer from my one using the preprocessor to do it the old-school way.
Edit:
How It Works
Here I will replicate the code above, but with the types simplified and the code drawn out more, with copious comments. Mind you, I did not understand the code very well before I went through this exercise, I don't understand it completely now, and I certainly won't remember how it works tomorrow. Caveat maintainer.
Here's the code we aren't allowed to change, with the private member:
// we can use any type of value, but int is simple
typedef int value_type;
// this structure holds value securely. we think.
struct FortKnox {
FortKnox() : value(0) {}
private:
value_type value;
};
Now for the heist:
// define a type which is a pointer to the member we want to steal
typedef value_type FortKnox::* stolen_mem_ptr;
// this guy is sort of dumb, but he knows a backdoor in the standard
template<typename AccompliceTag, stolen_mem_ptr MemPtr>
struct Robber {
friend stolen_mem_ptr steal(AccompliceTag) {
return MemPtr; // the only reason we exist: to expose the goods
}
};
// this guy doesn't know how to get the value, but he has a friend who does
struct Accomplice {
friend stolen_mem_ptr steal(Accomplice);
};
// explicit instantiation ignores private access specifier on value
// we cannot create an object of this type, because the value is inaccessible
// but we can, thanks to the C++ standard, use this value in this specific way
template struct Robber<Accomplice, &FortKnox::value>;
// here we create something based on secure principles, but which is not secure
class FortKnoxFacade : private FortKnox {
public:
value_type get_value() const {
// prepare to steal the value
// this theft can only be perpetrated by using an accomplice
stolen_mem_ptr accessor = steal(Accomplice()); // it's over now
// dereference the pointer-to-member, using this as the target
return this->*accessor;
}
};
int main() {
FortKnoxFacade fort;
return fort.get_value();
}
How about something more brutal?
// MY CODE -- module "b.h"
# define private protected
# include <a.h>
# undef private
class B : private A {
// now you can access "private" members and methods in A
The best-packaged version I know of this idiom is as follows:
template<class Tag,typename Tag::type MemberPtr>
struct access_cast{
friend typename Tag::type get(Tag){return MemberPtr;};
};
template<class Tag,class MemberPtr>
struct access_tag{
typedef MemberPtr type;
friend type get(Tag);
};
class A {
public:
auto x() const {return x_;};
private:
int x_ = 9;
};
#include <iostream>
struct AMemTag: access_tag<AMemTag,int A::*>{}; //declare tag
template struct access_cast<AMemTag,&A::x_>; //define friend get function
int main() {
A a;
std::cout<<a.x()<<"\n";
a.*get(AMemTag()) = 4; //dereference returned member pointer and modify value
std::cout<<a.x()<<"\n";
}
See it work.

how to generalize an interface to require a return value of some tuple?

I am using the SOCI library which has good support for boost and std::tuple<>.
My intention is to define a abstract interface called SOCI_Streamable which requires a method that returns some tuple.
I have it working for a specific tuple in gcc 4.7.2, but I need help abstracting this interface to work for any tuple.
In other words, I would like to convert this requirement into code: a class satisfies the requirements for SOCI_Streamable if it can return some kind of std::tuple - I don't care what kind.
A significant change in the code below is fine, as long as it satisfies the requirement. I suspect some kind of template code or maybe even CRTP is required, but I'm not sure.
#include<tuple>
// want to generalize next line to any std::tuple<>
typedef std::tuple<int const&,char const> some_tuple;
class SOCI_Streamable
{
public:
virtual some_tuple obj_as_tuple() const = 0;
};
class Foo :
public SOCI_Streamable
{
public:
virtual some_tuple obj_as_tuple() const
{
return std::forward_as_tuple( m_int, m_char );
}
private:
int m_int;
char m_char;
};
int main( int argc, char* argv[] )
{
}
template <class A,class B>
class SOCI_Streamable
{
public:
typedef std::tuple<A,B> Tuple;
virtual Tuple obj_as_tuple() const = 0;
};
class Foo :
public SOCI_Streamable<int const&,char const>
{
If you can specify the types at the implementer level, this should work. But that does change the single interface into a family of interfaces.. let me see if there is a better way
.

C++ template specify type by Enum

I'm facing a problem :
I want to create a function which calls a specific template type constructor depending on a enum that the function will receive. By that i mean :
typedef ____ (Class<whatever>::*tabType)(int flag);
template<typename T>
static Class* Class<t>::createClassInstance(enum precision)
{
static const ___ createTab[] = {
Class<int>,
Class<double>
}
return (new createTab[precision](1));
}
There are a number of ways of achieving this sort of thing, but it sounds like you want to create an array (or map) of factory methods (one for each class), indexed by the enum variable. Each one calls the relevant constructor, and returns a new object of that type.
Of course, for this to make any sense, all of the classes must derive from a common base.
If the enum value is dynamic as a function argument, you'll have to use either a dispatch table or switch/if-else. Notice that your pseudo code does not clearly explain the requirement. Say, what exactly the createInstance function you wish to define and how is it going to be called?
I would say, just construct a std::map that maps the enum to a factory function (boost::function<>). Then you just add one entry for each type that you want, with its corresponding enum. To actually construct the factory functions. You can either have some static Create() function for each class and store a function pointer. Or, you can use Boost.Lambda constructor/destructor functors. Or, you can use Boost.Bind to construct functors that wrap a factory function that requires some number of parameters. Here is an example:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/lambda/construct.hpp>
#include <map>
struct Base { };
struct Derived1 : public Base { };
struct Derived2 : public Base {
static Base* Create() { return new Derived2; };
};
struct Derived3 : public Base {
int value;
Derived3(int aValue) : value(aValue) { };
static Base* Create(int aValue) { return new Derived3(aValue); };
};
enum DerivedCreate { ClassDerived1, ClassDerived2, ClassDerived3 };
int main() {
std::map< DerivedCreate, boost::function< Base*() > constructor_map;
constructor_map[ClassDerived1] = boost::lambda::new_ptr<Derived1>();
constructor_map[ClassDerived2] = &Derived2::Create;
constructor_map[ClassDerived3] = boost::bind(&Derived3::Create, 42);
//now you can call any constructor as so:
Base* ptr = constructor_map[ClassDerived2]();
};
I might have made some slight syntax mistakes, but basically you should be able make the above work. Also, the fact that you have several class templates plays no role, once they are instantiated to a concrete class (like Class<int> or Class<double>) they are just like any other class, and the above idea should remain valid.
Extending your example, something like the following works:
enum Prec {INT, DOUBLE};
struct Base
{
virtual ~Base () = 0 {}
};
template<typename T> struct Class : public Base
{
static Base* create (int flag) {return new Class<T> (flag);}
Class (int flag) {}
};
typedef Base* (*Creator) (int flag);
Base* createClassInstance (Prec prec)
{
static const Creator createTab[] = {
Class<int>::create,
Class<double>::create
};
return createTab[prec] (1);
}
int main (int argc, char* argv[])
{
Base* c = createClassInstance (DOUBLE);
return 0;
}