I see at least 2 separate problems related to the diamond class hierarchy (note the example code below is in C++ but I believe my question is language-agnostic):
class A
{
public:
virtual ~A() = default;
virtual void f()
{}
};
class B : public A
{
public:
void f()
{
std::cout << "B" << std::endl;
}
};
class C : public A
{
public:
void f()
{
std::cout << "C" << std::endl;
}
};
class D : public B, public C
{
};
D d;
d.f();
Problem 1: Do B and C share one common instance of A or do they both have a separate instance? (Yes, I know how it's resolved in C++ but the general problem remains.)
Problem 2: Call to d.f() is ambiguous.
My question is - when people talk about the Diamond Problem which problem do they actually mean? 1 or 2? Or possibly both?
Says Wikipedia:
The "diamond problem" (sometimes referred to as the "Deadly Diamond of Death"[6]) is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If there is a method in A that B and C have overridden, and D does not override it, then which version of the method does D inherit: that of B, or that of C?
That's your "problem 2".
When people talk about the diamond problem, they usually don't distinguish between these two problems. But sometimes they do, especially if they're explaining a mitigating feature of some particular language.
"Diamond problem" is a colloquial expression that doesn't have a universally accepted formal definition. You can interpret it as "the problem of multiple inheritance nets"... for which there are various solutions.
Related
I have a function that has a lot of parameters. (4-7 parameters)
For simplicity, this is an example:-
class B{
friend class C;
int f(int param1,float param2, structA a, structB b){
//... some code ...
}
//.... other functions ....
};
Sometimes, I want to encapsulate it under another (more-public) function that has the same signature:-
class C{
B* b;
public: int g(int param1,float param2, structA a, structB b){
return b->f(param1,param2,a,b);
}
//.... other functions ....
};
In my opinion, the above code is :-
tedious
causes a bit of maintainability problem
human error-prone
Is there any C++ technique / magic / design-pattern to assist it?
In the real case, it happens mostly in edge-cases that composition is just a little more suitable than inheritance.
I feel that <...> might solve my problem, but it requires template from which I want to avoid.
but it requires template from which I want to avoid.
That's, in my opinion, the wrong mindset to have. You should avoid templates if you have a very good reason to do so, otherwise you should embrace them - they are a core feature of the C++ language.
With a variadic template, you can create a perfect-forwarding wrapper as follows:
class C{
B* b;
public:
template <typename... Ts>
int g(Ts&&... xs){
return b->f(std::forward<Ts>(xs)...);
}
};
The above g function template will accept any number of arguments and call b->f by perfectly-forwarding them.
(Using std::forward allows your wrapper to properly retain the value category of the passed expressions when invoking the wrapper. In short, this means that no unnecessary copies/moves will be made and that references will be correctly passed as such.)
In a public header:
using f_sig = int(int param1,float param2, structA a, structB b);
class hidden;
class famous {
hidden* pImpl
public:
f_sig g;
};
In your .cpp:
class hidden {
friend class famous;
f_sig f;
};
Now, you cannot use this pattern to define what f or g does, but this does declair their signatures. And if your definition doesn't match the declaration you get an error.
int hidden::f(int param1,float param2, structA a, structB b) {
std::cout << "f!";
}
int famous::g(int param1,float param2, structA a, structB b) {
return pImpl->f(param1, param2, a, b);
}
type the signatures wrong above, and you'll get a compile-time error.
How can I set a function pointer depending on some condition to functions with different signature?
Example:
short int A()
{
return 0;
}
long int B()
{
return 0;
}
void main()
{
std::function<short int()> f = A;
f();
if(true)
{
//error
f = B;
}
}
How can use the same function pointer for two functions with different signature?
Is it possible?
If is not, there is an efficient way to call the appropriate function depending on behavior instead of use a variable and split the whole code with if statements?
EDIT / EXPANSION ("2nd case")
#include <SDL.h>
class Obj { //whatever ...}
class A
{
private:
Uint16 ret16() { return SDL_ReadLE16(_pFile); }
Uint32 ret32() { return SDL_ReadLE32(_pFile); }
_pFile = nullptr;
public:
Obj* func()
{
Obj obj = new Obj();
_pFile = SDL_RWFromFile("filename.bin","r"));
auto ret = std::mem_fn(&SHPfile::ret16);
if(true)
{
ret = std::mem_fn(&SHPfile::ret32);
}
//ret();
// continue whatever
// ....
SDL_RWclose(_pFile);
return *obj;
}
}
I have a compilation error on a similar case using the Uint16 and Uint32 variable of SDL 2 library, using std::mem_fn
the compiler give me this error (relative to my code, but it's implemented in a way like the above example):
error: no match for ‘operator=’ (operand types are ‘std::_Mem_fn<short unsigned int (IO::File::*)()>’ and ‘std::_Mem_fn<unsigned int (IO::File::*)()>’)
To resolve this compilation error, I forced both the function to return a int type.
Is there a better way?
Or I did something wrong?
The comments already say that clang accepts the code as is, and I can now say that GCC 4.8.4 and GCC 4.9.2 both accept it as well, after fixing void main() to say int main().
This use of std::function is perfectly valid. The C++11 standard says:
20.8.11.2 Class template function [func.wrap.func]
function& operator=(const function&);
function& operator=(function&&);
function& operator=(nullptr_t);
There is no template assignment operator here, so assignment of B could only construct a new temporary function<short int()> object, and move-assign from that. To determine whether the construction of that temporary is possible:
20.8.11.2.1 function construct/copy/destroy [func.wrap.func.con]
template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);
7 Requires: F shall be CopyConstructible. f shall be Callable (20.8.11.2) for argument types ArgTypes and return type R. The copy constructor and destructor of A shall not throw exceptions.
20.8.11.2 Class template function [func.wrap.func]
2 A callable object f of type F is Callable for argument types ArgTypes and return type R if the expression INVOKE(f, declval<ArgTypes>()..., R), considered as an unevaluated operand (Clause 5), is well formed (20.8.2).
20.8.2 Requirements [func.require]
2 Define INVOKE(f, t1, t2, ..., tN, R) as INVOKE(f, t1, t2, ..., tN) implicitly converted to R.
1 Define INVOKE(f, t1, t2, ..., tN) as follows:
... (all related to pointer-to-member types)
f(t1, t2, ..., tN) in all other cases.
In short, this means that std::function<short int()> can be used with any function that can be called with no arguments, and which has a return type that can be implicitly converted to short. long clearly can be implicitly converted to short, so there is no problem whatsoever.
If your compiler's library doesn't accept it, and you cannot upgrade to a more recent version, one alternative is to try boost::function instead.
Aaron McDaid points out lambdas as another alternative: if your library's std::function is lacking, you can write
std::function<short int()> f = A;
f = []() -> short int { return B(); };
but if you take this route, you can take it a step further and avoid std::function altogether:
short int (*f)() = A;
f = []() -> short int { return B(); };
This works because lambas that don't capture anything are implicitly convertible to a pointer-to-function type that matches the lambda's arguments and return type. Effectively, it's short for writing
short int B_wrapper() { return B(); }
...
f = B_wrapper;
Note: the conversion from long to short may lose data. If you want to avoid that, you can use std::function<long int()> or long int (*)() instead.
No, you can't do that in a statically typed language unless your types all have a common super type, and C++ doesn't have that for primitives. You would need to box them into an object, then have the function return the object.
However, if you did that, you may as well just keep an object pointer around and use that instead of a function pointer, especially since it's going to make it easier to actually do something useful with the result without doing casts all over the place.
For example, in a calculator I wrote in Java, I wanted to work with BigInteger fractions as much as possible to preserve precision, but fallback to doubles for operations that returned irrational numbers. I created a Result interface, with BigFractionResult and DoubleResult implementations. The UI code would call things like Result sum = firstOperand.add(otherOperand) and didn't have to care which implementation of add it was using.
The cleanest option that comes to mind is templates:
#include <iostream>
using namespace std;
template <typename T>
T foo() {
return 0;
}
int main() {
long a = foo<long>();
cout << sizeof a << " bytes with value " << a << endl;
int b = foo<int>();
cout << sizeof b << " bytes with value " << b << endl;
short c = foo<short>();
cout << sizeof c << " bytes with value " << c << endl;
return 0;
}
In ideone.com this outputs:
4 bytes with value 0
4 bytes with value 0
2 bytes with value 0
Hopefully this is what you needed.
If for some reason you really need to pass an actual function around, I would recommend looking into std::function and trying to write some template code using that.
Here is a variadic template that prints parameters.
#include <string>
#include <iostream>
void Output() {
std::cout<<std::endl;
}
template<typename First, typename ... Strings>
void Output(First arg, const Strings&... rest) {
std::cout<<arg<<" ";
Output(rest...);
}
int main() {
Output("I","am","a","sentence");
Output("Let's","try",1,"or",2,"digits");
Output(); //<- I do not want this to compile, but it does.
return 0;
}
Is there a way to get this functionality without having the "no parameter" call work, and without having to write two functions every time?
You might want to keep the separation of the first and the rest of the parameters, you can use:
template<typename First, typename ... Rest>
void Output(First&& first, Rest&&... rest) {
std::cout << std::forward<First>(first);
int sink[]{(std::cout<<" "<<std::forward<Rest>(rest),0)... };
(void)sink; // silence "unused variable" warning
std::cout << std::endl;
}
Note that I used perfect forwarding to avoid copying any parameters. The above has the additional benefit to avoid recursion and therefore is likely to produce better (faster) code.
The way I wrote sink also guarantees that the expressions expanded from rest are evaluated left-to-right - which is important when compared to the naïve approach of just writing a helper function template<typename...Args>void sink(Args&&...){}.
Live example
Call the function from a forwarding type function and have a static_assert like this:
template <typename ... Args>
void forwarder(Args ... args) {
static_assert(sizeof...(args),"too small");
Output(args...);
}
As far as I see there are two questsions:
How to avoid Output() calls with no parameters.
Is there a simpler way to end the compile time recursion?
My solution to item 1 is as follows:
template<typename T>
void Output(const T & string) {
std::cout<<string<<std::endl;
}
template<typename First, typename ... Strings>
void Output(const First & arg, const Strings & ... rest) {
std::cout<<arg<<" ";
Output(rest...);
}
Basically, instead of ending the recursion when the template list is empty, I end it when it only contains one type. There is one difference between the above and the code from the question: if does not output any space after the last item. Instead it just outputs the newline.
For question number two see the answer by Daniel Frey above. I really liked this solution, although it took some time to grasp it (and I upvoted the answer). At the same time I find that it makes the code harder to read/understand and therefore harder to maintain. Currently I would not not use that solution in anything but small personal code snippets.
What does "Overloaded"/"Overload" mean in regards to programming?
It means that you are providing a function (method or operator) with the same name, but with a different signature.
For example:
void doSomething();
int doSomething(string x);
int doSomething(int a, int b, int c);
Basic Concept
Overloading, or "method overloading" is the name of the concept of having more than one methods with the same name but with different parameters.
For e.g. System.DateTime class in c# have more than one ToString method. The standard ToString uses the default culture of the system to convert the datetime to string:
new DateTime(2008, 11, 14).ToString(); // returns "14/11/2008" in America
while another overload of the same method allows the user to customize the format:
new DateTime(2008, 11, 14).ToString("dd MMM yyyy"); // returns "11 Nov 2008"
Sometimes parameter name may be the same but the parameter types may differ:
Convert.ToInt32(123m);
converts a decimal to int while
Convert.ToInt32("123");
converts a string to int.
Overload Resolution
For finding the best overload to call, compiler performs an operation named "overload resolution". For the first example, compiler can find the best method simply by matching the argument count. For the second example, compiler automatically calls the decimal version of replace method if you pass a decimal parameter and calls string version if you pass a string parameter. From the list of possible outputs, if compiler cannot find a suitable one to call, you will get a compiler error like "The best overload does not match the parameters...".
You can find lots of information on how different compilers perform overload resolution.
A function is overloaded when it has more than one signature. This means that you can call it with different argument types. For instance, you may have a function for printing a variable on screen, and you can define it for different argument types:
void print(int i);
void print(char i);
void print(UserDefinedType t);
In this case, the function print() would have three overloads.
It means having different versions of the same function which take different types of parameters. Such a function is "overloaded". For example, take the following function:
void Print(std::string str) {
std::cout << str << endl;
}
You can use this function to print a string to the screen. However, this function cannot be used when you want to print an integer, you can then make a second version of the function, like this:
void Print(int i) {
std::cout << i << endl;
}
Now the function is overloaded, and which version of the function will be called depends on the parameters you give it.
Others have answered what an overload is. When you are starting out it gets confused with override/overriding.
As opposed to overloading, overriding is defining a method with the same signature in the subclass (or child class), which overrides the parent classes implementation. Some language require explicit directive, such as virtual member function in C++ or override in Delphi and C#.
using System;
public class DrawingObject
{
public virtual void Draw()
{
Console.WriteLine("I'm just a generic drawing object.");
}
}
public class Line : DrawingObject
{
public override void Draw()
{
Console.WriteLine("I'm a Line.");
}
}
An overloaded method is one with several options for the number and type of parameters. For instance:
foo(foo)
foo(foo, bar)
both would do relatively the same thing but one has a second parameter for more options
Also you can have the same method take different types
int Convert(int i)
int Convert(double i)
int Convert(float i)
Just like in common usage, it refers to something (in this case, a method name), doing more than one job.
Overloading is the poor man's version of multimethods from CLOS and other languages. It's the confusing one.
Overriding is the usual OO one. It goes with inheritance, we call it redefinition too (e.g. in https://stackoverflow.com/users/3827/eed3si9n's answer Line provides a specialized definition of Draw().
Partial template specialization is one of the most important concepts for generic programming in C++. For example: to implement a generic swap function:
template <typename T>
void swap(T &x, T &y) {
const T tmp = x;
y = x;
x = tmp;
}
To specialize it for a vector to support O(1) swap:
template <typename T, class Alloc>
void swap(vector<T, Alloc> &x, vector<T, Alloc> &y) { x.swap(y); }
So you can always get optimal performance when you call swap(x, y) in a generic function;
Much appreciated, if you can post the equivalent (or the canonical example of partial specialization of the language if the language doesn't support the swap concept) in alternative languages.
EDIT: so it looks like many people who answered/commented really don't known what partial specialization is, and that the generic swap example seems to get in the way of understanding by some people. A more general example would be:
template <typename T>
void foo(T x) { generic_foo(x); }
A partial specialization would be:
template <typename T>
void foo(vector<T> x) { partially_specialized_algo_for_vector(x); }
A complete specialization would be:
void foo(vector<bool> bitmap) { special_algo_for_bitmap(bitmap); }
Why this is important? because you can call foo(anything) in a generic function:
template <typename T>
void bar(T x) {
// stuff...
foo(x);
// more stuff...
}
and get the most appropriate implementation at compile time. This is one way for C++ to achieve abstraction w/ minimal performance penalty.
Hope it helps clearing up the concept of "partial specialization". In a way, this is how C++ do type pattern matching without needing the explicit pattern matching syntax (say the match keyword in Ocaml/F#), which sometimes gets in the way for generic programming.
D supports partial specialization:
Language overview
Template feature comparison (with C++ 98 and 0x).
(scan for "partial" in the above links).
The second link in particular will give you a very detailed breakdown of what you can do with template specialization, not only in D but in C++ as well.
Here's a D specific example of swap. It should print out the message for the swap specialized for the Thing class.
import std.stdio; // for writefln
// Class with swap method
class Thing(T)
{
public:
this(T thing)
{
this.thing = thing;
}
// Implementation is the same as generic swap, but it will be called instead.
void swap(Thing that)
{
const T tmp = this.thing;
this.thing = that.thing;
that.thing = tmp;
}
public:
T thing;
}
// Swap generic function
void swap(T)(ref T lhs, ref T rhs)
{
writefln("Generic swap.");
const T tmp = lhs;
lhs = rhs;
rhs = tmp;
}
void swap(T : Thing!(U))(ref T lhs, ref T rhs)
{
writefln("Specialized swap method for Things.");
lhs.swap(rhs);
}
// Test case
int main()
{
auto v1 = new Thing!(int)(10);
auto v2 = new Thing!(int)(20);
assert (v1.thing == 10);
assert (v2.thing == 20);
swap(v1, v2);
assert (v1.thing == 20);
assert (v2.thing == 10);
return 0;
}
I am afraid that C# does not support partial template specialization.
Partial template specialization means:
You have a base class with two or more templates (generics / type parameters).
The type parameters would be <T, S>
In a derived (specialized) class you indicate the type of one of the type parameters.
The type parameters could look like this <T, int>.
So when someone uses (instantiates an object of) the class where the last type parameter is an int, the derived class is used.
Haskell has overlapping instances as an extension:
class Sizable a where
size :: a -> Int
instance Collection c => Sizable c where
size = length . toList
is a function to find size of any collection, which can have more specific instances:
instance Sizable (Seq a) where
size = Seq.length
See also Advanced Overlap on HaskellWiki.
Actually, you can (not quite; see below) do it in C# with extension methods:
public Count (this IEnumerable<T> seq) {
int n = 0;
foreach (T t in seq)
n++;
return n;
}
public Count (this T[] arr) {
return arr.Length;
}
Then calling array.Count() will use the specialised version. "Not quite" is because the resolution depends on the static type of array, not on the run-time type. I.e. this will use the more general version:
IEnumerable<int> array = SomethingThatReturnsAnArray();
return array.Count();
C#:
void Swap<T>(ref T a, ref T b) {
var c = a;
a = b;
b = c;
}
I guess the (pure) Haskell-version would be:
swap :: a -> b -> (b,a)
swap a b = (b, a)
Java has generics, which allow you to do similar sorts of things.