The ability to call the destructor

Pages: 123
I was just looking over something on parashift about destructors (http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.5 ... and then onwards) and it made me think... Should the ability to explicitly call a destructor be removed from C++?

EDIT* What do you guys think?
Last edited on
No. Removing features because they can be misused is the Java philosophy. The C++ philosophy is giving the programmer as much freedom as possible.
If you call destructors on automatic storage data, that's your problem. That's not how explicit destructor calls are meant to be used. They're meant for implementing custom allocators.
helios wrote:
They're meant for implementing custom allocators.

Could you expand on this please? I don't mean to sound ignorant but I don't really know what that means. I'm much more comfortable with the C++ language than I used to be but I think as I'm "pre-degree" I might have missed out on some important topics because sometimes you guys' conversations go straight over my head.
Suppose you're implementing a vector class. Just new T[n] is no good, because you can't pass parameters to the constructor for each object, so what do you do? You allocate the array with malloc(), then use placement new to manually call constructors. When, say, pop_back() is called, then you explicitly call the destructor.
closed account (EzwRko23)
IMHO this should not be romoved. This feature is completely ok and I don't see a reason how this could be misused.


Removing features because they can be misused is the Java philosophy.


No. The Java philosophy is to restrain from **adding** features that are useful in 1% cases and **get in your way** in the rest 99% of cases. Therefore, they never had to remove any feature, yet.


The C++ philosophy is giving the programmer as much freedom as possible.


This is strange statement, if you realise how limited C++ is, especially in the support for creating powerful libraries. I can't see this freedom. But if you compare it with Pascal or Basic, maybe you are right.
The 'freedom' helios mentioned is the freedom of using features:
C++ is designed to give the programmer choice, even if this makes it possible for the programmer to choose incorrectly
[The Design and Evolution of C++]
This is strange statement, if you realise how limited C++ is, especially in the support for creating powerful libraries.


Spoken like a true C++ novice. I guess I'd like to see some support for such a statement.

xorebxebx: Honestly, I don't know why you even bother to post.
closed account (EzwRko23)

C++ is designed to give the programmer choice, even if this makes it possible for the programmer to choose incorrectly


This can be said about virtually any language.


Spoken like a true C++ novice. I guess I'd like to see some support for such a statement.


So please implement a C++ equivalent of the "getOrElseUpdate" method in Scala:

1
2
3
4
5
6
7
8
val cache = collection.mutable.Map[Int, Int]()

def cachedFunction(x: Int): Int = {
  cache.getOrElseUpdate(x) {
     // costly computation goes here
  }
}


You cannot implement it because there are 2 extremely powerful things missing in C++: closures (which Java had since 1.1) and lazy evaluation.

Another large portion of libraries you cannot implement are things requiring reflection, e.g. ORMs or IoC containers.


Last edited on
After reading over the wiki article, it appears that closures are going to implemented (called lambada functions) in C++0x.

Lazy evaluation in C++, see: http://boost-spirit.com/dl_docs/phoenix-2/libs/spirit/phoenix/doc/html/phoenix/introduction.html

Dunno about reflection though.
xorebxebx
The Java philosophy is ... Therefore, they never had to remove any feature, yet.

They just deprecate classes/methods with each release and make a mess of new features (like templates).

... if you realise how limited C++ is
Another large portion of libraries you cannot implement are things requiring ...

The idea isn't to create a langauge with more features than other languages. The idea is to create a programming environment that supports libraries to do the fancy things you want to do.

For example, although Java supports reflection, you don't use it all the time. But you have to live with the cost of supporting reflection in every Java app. That goes for every other "improvement" it has.
Last edited on

So please implement a C++ equivalent of the "getOrElseUpdate" method in Scala:


Can somebody tell me what this method does? I don't know Scala, and I'd at least like to ponder the question.
closed account (z05DSL3A)
def getOrElseUpdate (key: A, op: ⇒ B) : B
If given key is already in this map, returns associated value.
Otherwise, computes value from given expression op, stores with key in map and returns that value.

key: the key to test
op: the computation yielding the value to associate with key, if key is previously unbound.
returns: the value associated with key (either previously or as a result of executing the method).


Any help?
A rough draft (ver. 2, simplified a bit):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <cmath>
#include <iostream>
#include <map>
#include <functional>

template <typename Operation>
struct CachedFunction
: public std::unary_function<
    typename Operation::argument_type,
    typename Operation::result_type>
{
    typedef typename Operation::argument_type Arg;
    typedef typename Operation::result_type Result;

    typedef std::map<Arg, Result> map_t;
    
    map_t cache;
    Operation operation;

    CachedFunction(Operation op) : cache(), operation(op) {}
    
    Result operator()(const Arg& arg)
    {
        typedef typename map_t::value_type value_type;
        typedef typename map_t::const_iterator const_iterator;

        const_iterator it = cache.find(arg);

        if (it == cache.end())
        {
            it = cache.insert(value_type(arg, operation(arg))).first;
        }
#ifdef DEBUG
        else
        {
            std::cout << "<cached> ";
        }
#endif
        return it->second;
    }
};


template <typename Operation>
CachedFunction<Operation> make_cached_op(Operation op)
{
    return CachedFunction<Operation>(op);
}

int main()
{
    auto cachedSqrt = make_cached_op(std::ptr_fun<size_t,double>(std::sqrt));
    
    for (size_t i = 0; i < 2; i++)
    {
        for (size_t j = 0; j < 100; j++)
        {
            std::cout << cachedSqrt(j) << std::endl;
        }
    }
    return 0;
}


With this code, make_cached_op() will turn any unary_function into a cached function.

It's a silly argument and not worth responding to, really. I'm a huge fan of Python and can wittle down hundreds of lines of C++ code into a few lines of Python. They both excel in different tasks.
Last edited on
closed account (EzwRko23)
Yeah, still cumbersome to use (cannot define functions in-place), but nice try. What about binary functions?

1
2
3
4
5
6
7
val cache = collection.mutable.Map[(Int, Int), Int]()

def cachedFunction(x: Int, y: Int): Int = {
  cache.getOrElseUpdate((x, y)) {
     // costly computation goes here
  }
}



The idea isn't to create a langauge with more features than other languages. The idea is to create a programming environment that supports libraries to do the fancy things you want to do.


Scala and Java have far **less** language features than C++ and these features are much more consistent and not redundant as in C++, yet the programming environment is much richer (because of standard libraries). The important thing is not only to choose the right set of features but also to make them cooperate.


For example, although Java supports reflection, you don't use it all the time. But you have to live with the cost of supporting reflection in every Java app


You do use it. The VM underneath uses it all the time e.g. to support garbage collection and access control, things which are totally absent in the C++ world. If you use ORMs or IoC or web frameworks, they use it for the core functionality. But the cost of that is much lower than the cost of supporting exceptions in C++ - just the memory taken on a per-class basis. There is no runtime execution cost associated with supporting reflection, nor any per-object memory cost.
Last edited on
Google the castor library for C++. It might be what you said is impossible to do in C++.
closed account (EzwRko23)
Castor is for logic programming. Anyway - what is the point? What is the point of forcing foreign paradigms in C++, instead of chosing the right tool for the job? There are languages designed especially for FP or LP or hybrids, and it is much more convenient to do FP in Haskell, LP in Prolog or mixed paradigms in Scala than to mimic them in C++ which is a purely imperative language. Well, just as doing OOP in C is possible, doesn't mean you should do it. It just doesn't feel natural and the deeper you get into it the more problems arise.
Last edited on
I actually have to agree with xorebxebx here. Just as the builder would bring more than a mere hammer (even if it is a very flexible hammer that he can make simulate other tools) to fix things, the programmer should bring more than a single programming paradigm in his mental toolbox.

And your ranting about Scala has got me. I'm going to take a look at it. I need to learn more languages anyway.
This was the original statement:

This is strange statement, if you realise how limited C++ is, especially in the support for creating powerful libraries.


Nothing xorebxebx has said has supported the original statement, unless the claim is that C++ is limited by the fact that
it is imperative by nature and does not intrinsically support logic programming and functional programming at the same
time. Though no language supports all three intrinsically. C++ does the best it can to provide, using only imperative
constructs, ways to implement logic programming and functional programming.

But this is all a non sequitur anyway; I would consider the STL and the boost libraries to be quite powerful.

I agreed with only his post previous to mine (excepting the "Castor is for logic programming" part because I don't know about it); I don't necessarily agree with anything else he's ever said.
Last edited on
Pages: 123