These are chat archives for bluescarni/pagmo_reborn

10th
May 2016
Dario Izzo
@darioizzo
May 10 2016 08:33
SO, finished the low discrepancy stuff (committed) should I start with
1) Stochastic problems
2) The algorithm
?
Marcus Märtens
@CoolRunning
May 10 2016 08:43
:clap:
Francesco Biscani
@bluescarni
May 10 2016 09:04
maybe the stochastic problem, so then the problem is finished hopefully?
Dario Izzo
@darioizzo
May 10 2016 09:04
ok, I also thought so ....
Francesco Biscani
@bluescarni
May 10 2016 09:20
did you take a look at those out-of-bounds accesses we identified the other day?
Dario Izzo
@darioizzo
May 10 2016 09:21
I think i committed a solution already. It was in the sort pop con stuff right?
Its the famous commit where I overwrote your problem .... but if you go to the end you should see the "solution"
the rest looks good
Dario Izzo
@darioizzo
May 10 2016 09:27
that is checked in the following call to the other overload .... so it will throw. But I can double-check also there ...
Francesco Biscani
@bluescarni
May 10 2016 09:27
input_f[0].size() - 1u this can still fail right?
Dario Izzo
@darioizzo
May 10 2016 09:28
it will not fail, it will do something but then, if input_f[0].size() < 1 the next call will throw
Francesco Biscani
@bluescarni
May 10 2016 09:28
it will try to allocate a vector of 2^64-1 or not?
Dario Izzo
@darioizzo
May 10 2016 09:29
yep
Francesco Biscani
@bluescarni
May 10 2016 09:31
I'd fix it but I don't know what error message to give :)
Dario Izzo
@darioizzo
May 10 2016 09:31
I am fixing it
have a look
Francesco Biscani
@bluescarni
May 10 2016 09:34
:+1:
Dario Izzo
@darioizzo
May 10 2016 10:19
#define PAGMO_REGISTER_PROBLEM(prob) CEREAL_REGISTER_TYPE_WITH_NAME(pagmo::detail::prob_inner<prob>,#prob)
I think this should go in serialization.hpp not in problem.hpp
Francesco Biscani
@bluescarni
May 10 2016 10:23
the problem with that is that pagmo::detail::prob_inner is not visible from serialization.hpp
This message was deleted
Dario Izzo
@darioizzo
May 10 2016 10:26
Including the problem.hpp from serialization?
Francesco Biscani
@bluescarni
May 10 2016 10:27
I think that would make less sense.. what is the problem with including problem.hpp in concrete problems?
Dario Izzo
@darioizzo
May 10 2016 10:28
The fact is that I (stupid me) spent 30 min now to understand why my inventory.hpp was not compiling to find out I did not include problem.hpp. The error message you get if you use the macro without including is "expecting type or class declaration before blah blah" and you get it in the cpp file where you include iventory.hpp
From a logic point of view, once you include serialization.hpp you feel secure that you have included all the stuff related to serialziation ....which did not help in fixing this
anyway .. its probably just me
Francesco Biscani
@bluescarni
May 10 2016 10:30
well in the doxygen it should be documented that the macro is defined in problem.hpp, so that one needs to include it in order to use it. But it's a fair point
what we could do would be to move the implementation of only prob_inner in its own detail/ header
then include it in both problem.hpp and serialization
Dario Izzo
@darioizzo
May 10 2016 11:49
template <typename T>
class has_set_seed: detail::sfinae_types
{
        template <typename U>
        static auto test0(const U &p) -> decltype(p.set_seed(std::declval<unsigned int>()));
        static no test0(...);
        static const bool implementation_defined =
            std::is_same<void>,decltype(test0(std::declval<const T &>()))>::value;
    public:
        /// static const boolean value flag
        static const bool value = implementation_defined;
};
here I need to check the existence of a method having signature void set_seed(unsigned int) {}
but void I cannot use in is_same ...
Francesco Biscani
@bluescarni
May 10 2016 11:50
is that a syntax error in is_same?
Dario Izzo
@darioizzo
May 10 2016 11:50
oh wait ... maybe let me check
Francesco Biscani
@bluescarni
May 10 2016 11:51
there's another thing
should set_seed be a const or non const method?
Dario Izzo
@darioizzo
May 10 2016 11:51
non const
Francesco Biscani
@bluescarni
May 10 2016 11:51
ok then you need to change the implementation of the type trait as well
        template <typename U>
        static auto test0(const U &p) -> decltype(p.set_seed(std::declval<unsigned int>()));
        static no test0(...);
        static const bool implementation_defined =
            std::is_same<void>,decltype(test0(std::declval<const T &>()))>::value;
here you are marking the references as const, but you are looking for a non-const method
        template <typename U>
        static auto test0(U &p) -> decltype(p.set_seed(std::declval<unsigned int>()));
        static no test0(...);
        static const bool implementation_defined =
            std::is_same<void>,decltype(test0(std::declval<T &>()))>::value;
should be something like this
Dario Izzo
@darioizzo
May 10 2016 11:53
:) you are so much better than the compiler !!!
on the const, yes I knew that would have been my next thing
Francesco Biscani
@bluescarni
May 10 2016 11:54
:p so in principle here
static const bool implementation_defined =
            std::is_same<void>,decltype(test0(std::declval<T &>()))>::value;
you are requiring that set_seed returns void
Dario Izzo
@darioizzo
May 10 2016 11:54
One of the main problem I have with c++ development is that I am really bad at understanding the compiler erorr messages .....
Yes
except the syntax error still there ...
Francesco Biscani
@bluescarni
May 10 2016 11:55
which is fine but maybe we would want to let the user implement set_seed with whatever return value they want? maybe the old seed? anyway not really important
Dario Izzo
@darioizzo
May 10 2016 11:55
Do we want to give the user freedom? I say no.
He must comply with the way we want him to write down stuff. We may add a get_seed
no?
struct set_seed_02 
{
    void set_seed(unsigned int) const;
};

struct set_seed_03
{
    void set_seed(int);
};
these two pass the trait .... !!?
they should not ...
Francesco Biscani
@bluescarni
May 10 2016 11:57
so regarding the argument, that's the problem of C++ conversion rules :/
the constness should not pass, can you show me the type trait and how you check it
Dario Izzo
@darioizzo
May 10 2016 11:58
template <typename T>
class has_set_seed: detail::sfinae_types
{
        template <typename U>
        static auto test0(U &p) -> decltype(p.set_seed(std::declval<unsigned int>()));
        static no test0(...);
        static const bool implementation_defined =
            std::is_same<void,decltype(test0(std::declval<T &>()))>::value;
    public:
        /// static const boolean value flag
        static const bool value = implementation_defined;
};

template <typename T>
const bool has_set_seed<T>::value;
and this is how I check it
struct set_seed_00 {};

// The good one.
struct set_seed_01 
{
    void set_seed(unsigned int);
};

struct set_seed_02 
{
    void set_seed(unsigned int) const;
};

struct set_seed_03
{
    void set_seed(int);
};

struct set_seed_04 
{
    double set_seed(unsigned int);
};

BOOST_AUTO_TEST_CASE(has_set_seed_test)
{
    BOOST_CHECK((!has_set_seed<set_seed_00>::value));
    BOOST_CHECK((has_set_seed<set_seed_01>::value));
    BOOST_CHECK((!has_set_seed<set_seed_02>::value));
    BOOST_CHECK((!has_set_seed<set_seed_03>::value));
    BOOST_CHECK((!has_set_seed<set_seed_04>::value));
}
Francesco Biscani
@bluescarni
May 10 2016 12:01
it's actually correct
Dario Izzo
@darioizzo
May 10 2016 12:01
?
Francesco Biscani
@bluescarni
May 10 2016 12:01
in the same sense that you can call a const method from a non-const one
Dario Izzo
@darioizzo
May 10 2016 12:03
So we can enforce to write a const method, but not viceversa as a non const method "can be const" ?
Francesco Biscani
@bluescarni
May 10 2016 12:03
p.set_seed(std::declval<unsigned int>()) this is a valid use
if the set_seed method is const
in the same way if I write
auto p = ...; // non-const
p.some_const_method();
usually you want to enforce const-ness
it is also consistent with how function params work:
void foo(const int &);

int n; // non-const
foo(n);
in general calling const functions/methods on non-const objects is ok
Dario Izzo
@darioizzo
May 10 2016 12:07
Bottom line? I change the tests and document that the type_trait accepts a number of different signatures?
Francesco Biscani
@bluescarni
May 10 2016 12:07
all traits accept different signatues as long as conversions are allowed... the fitness traits for instance accept initializer lists as input params
traits are defined in terms of expressions that are legally called on those types
Dario Izzo
@darioizzo
May 10 2016 12:08
The argument kind of bothers me, more than the constness
Francesco Biscani
@bluescarni
May 10 2016 12:08
it will still show up as a warning when you actually instantiate the problems
you should document the trait as:
Dario Izzo
@darioizzo
May 10 2016 12:09
Ok, so i change the test and thats it. In the docs I refer to a signature void set_seed(unsigned int) {}
tell me
Francesco Biscani
@bluescarni
May 10 2016 12:10
This trait will be true if the expression p.set_seed(n) is valid, where p is a non-const instance of .... and n is an unsigned int
that's the most accurate way of describing it
Dario Izzo
@darioizzo
May 10 2016 12:10
done
Francesco Biscani
@bluescarni
May 10 2016 12:13
actually
This trait will be true if the expression p.set_seed(n) is valid and returns void, where p is a non-const instance of .... and n is an unsigned int
that's even more accurate :)
Dario Izzo
@darioizzo
May 10 2016 12:13
I would rather:
This trait will be true if the expression p.set_seed(n) is valid and returns void, where p is a non-const instance of \p T
Francesco Biscani
@bluescarni
May 10 2016 12:14
and about n?
Dario Izzo
@darioizzo
May 10 2016 12:14
needs not to be unsigned right?
as far as p.set_seed(n) gets casted to unsigned int it will pass .. or I am not understanding this correctly?
ah right I see your logic
Francesco Biscani
@bluescarni
May 10 2016 12:15
in the type trait you are testing the expression with unsigned: decltype(p.set_seed(std::declval<unsigned int>()))
it will work with whatever object is implicitly convertible to unsigned, but you don't need to state that, it's implied by the description of the expression
Dario Izzo
@darioizzo
May 10 2016 12:16
ah right I see your logic
Francesco Biscani
@bluescarni
May 10 2016 12:17
if you wanted to restrict it fully you could create a type which is implicitly convertible from unsigned
something like:
class uwrapper
{
    operator unsigned() const;
};
and then you test decltype(set_seed(std::declval<uwrapper>()) maybe
dunno something along these lines
now I am kinda curious
Francesco Biscani
@bluescarni
May 10 2016 12:35
yep does not work, it looks like it still goes through 2 chained automatic conversions
I hate automatic conversions
Marcus Märtens
@CoolRunning
May 10 2016 14:08
Git and me will never be friends.
Dario Izzo
@darioizzo
May 10 2016 14:40
@bluescarni ci sei?
Francesco Biscani
@bluescarni
May 10 2016 14:41
yeps
Dario Izzo
@darioizzo
May 10 2016 14:41
Help me on this if you have 5 mins ...
Francesco Biscani
@bluescarni
May 10 2016 14:41
I need to leave at 5 so yes ;)
Dario Izzo
@darioizzo
May 10 2016 14:42
I commited some shit
Look at the problem.cpp in test
The last lines.
The output is:
Running 11 test cases...
true
Problem name: 4s_02    
Global dimension:            1
    Fitness dimension:            3
    Number of objectives:            1
    Equality constraints dimension:        1
    Inequality constraints dimension:    1
    Lower bounds: [0]
    Upper bounds: [1]

    Has gradient: false
    User implemented gradient sparsity: false
    Has hessians: false
    User implemented hessians sparsity: false

    Function evaluations: 0
true, means that the type trait detects, correctly, the presence of the get_seed method in s_02
But then ...... if I construct a pagmo::problem with s_02, the method pagmo::problem.is_stochastic() returns false
WHAT HAVE I DONE????
Francesco Biscani
@bluescarni
May 10 2016 14:48
    virtual void set_seed(unsigned int seed) const override final
    {
        set_seed_impl(m_value, seed);
    }
why is this const
this passes down m_value to set_seed_impl as a const reference
so I think the type trait is tested with const s_02 as type instead of s_02
dunno if the diagnosis is completely correct but I'm fairly confident it's related to that
Dario Izzo
@darioizzo
May 10 2016 14:54
In file included from /home/dario/Documents/PaGMOreborn/tests/inventory.cpp:8:0:
/home/dario/Documents/PaGMOreborn/tests/../include/problem.hpp: In member function ‘void pagmo::problem::set_seed(unsigned int)’:
/home/dario/Documents/PaGMOreborn/tests/../include/problem.hpp:1027:33: error: passing ‘const pagmo::detail::prob_inner_base’ as ‘this’ argument discards qualifiers [-fpermissive]
             ptr()->set_seed(seed);
                                 ^
/home/dario/Documents/PaGMOreborn/tests/../include/problem.hpp:97:18: note:   in call to ‘virtual void pagmo::detail::prob_inner_base::set_seed(unsigned int)’
     virtual void set_seed(unsigned int) = 0;
                  ^
tests/CMakeFiles/inventory.dir/build.make:62: recipe for target 'tests/CMakeFiles/inventory.dir/inventory.cpp.o' failed
make[2]: *** [tests/CMakeFiles/inventory.dir/inventory.cpp.o] Error 1
CMakeFiles/Makefile2:115: recipe for target 'tests/CMakeFiles/inventory.dir/all' failed
make[1]: *** [tests/CMakeFiles/inventory.dir/all] Error 2
Makefile:94: recipe for target 'all' failed
thats why
and tried a number of const combinations :) but could not fix it. It only disappeared as soon as i introduced the const stuff ....
Francesco Biscani
@bluescarni
May 10 2016 14:55
ok I need to go but I know how to fix this :) but don't try random combination of const correctness just to make problems go away please :)
need to change the type of the unique_ptr to non const
and add another overload for ptr() which returns a non const pointer
Dario Izzo
@darioizzo
May 10 2016 14:56
that also does not work, I tried /.... but ok I will let you fix it
Francesco Biscani
@bluescarni
May 10 2016 14:56
the idea was that the inner object would be immutable so that it was made into a const pointer
but set_seed changes that
ok
that's another thing why we should do pull requests, with a sequence of commits it's really hard to see what was changed and to do code reviewing :(
Dario Izzo
@darioizzo
May 10 2016 15:01
yep, as agreed we will start the pull requests as soon as algorithm class is completed
One last thing, maybe helps you ..... the inventory class is correctly detected as stochastic. So that
Dario Izzo
@darioizzo
May 10 2016 15:06
inventory prob;
prob.set_seed(23u);
print(problem{prob});
correctly prints:
Problem name: Inventory problem (stochastic)    
Global dimension:            4
    Fitness dimension:            1
    Number of objectives:            1
    Equality constraints dimension:        0
    Inequality constraints dimension:    0
    Lower bounds: [0, 0, 0, 0]
    Upper bounds: [200, 200, 200, 200]

    Has gradient: false
    User implemented gradient sparsity: false
    Has hessians: false
    User implemented hessians sparsity: false

    Function evaluations: 0

Problem's extra info:
    Weeks: 4
    Sample size: 10
    Seed: 23
Denoting that in this case is_stochastic() returns true.
Dario Izzo
@darioizzo
May 10 2016 18:50
Any ideas?
Francesco Biscani
@bluescarni
May 10 2016 19:30
yeah I fixed it
Marcus Märtens
@CoolRunning
May 10 2016 19:30
Is there any convenient way to compile and run main.cpp? I would like to have some print-output and can't manage to get that from within BOOST-tests.
Francesco Biscani
@bluescarni
May 10 2016 19:31
how come printing does not work from the tests?
Dario Izzo
@darioizzo
May 10 2016 19:31
did you commit?
Francesco Biscani
@bluescarni
May 10 2016 19:32
committing now, I first commit the fix then I'll commit a bunch of changes to make it more difficult to repeat the same issue :)
Dario Izzo
@darioizzo
May 10 2016 19:32
what do you mean it does not print from the tests?
Marcus Märtens
@CoolRunning
May 10 2016 19:32
std::cout does not appear in the output
Dario Izzo
@darioizzo
May 10 2016 19:32
it is unactivated by make test, but if you go in the tests folder and run the binary it will show
cd tests
Marcus Märtens
@CoolRunning
May 10 2016 19:33
ahhh
Dario Izzo
@darioizzo
May 10 2016 19:33
./my_test
Francesco Biscani
@bluescarni
May 10 2016 19:33
ok pushed
we need also the is_stochastic override
Marcus Märtens
@CoolRunning
May 10 2016 19:36
Okay - found the .exe - works.
Dario Izzo
@darioizzo
May 10 2016 19:36
for the metaproblems?
Francesco Biscani
@bluescarni
May 10 2016 19:37
every translated problem now is stochastic
Dario Izzo
@darioizzo
May 10 2016 19:37
how come?
Francesco Biscani
@bluescarni
May 10 2016 19:37
it's the same as has_gradient, etc.
Dario Izzo
@darioizzo
May 10 2016 19:38
refresh my memory ....
Francesco Biscani
@bluescarni
May 10 2016 19:38
translate inherits from problem, which always has set_seed implemented
Dario Izzo
@darioizzo
May 10 2016 19:39
ah right
now I remember
tell me ...
I am trying to understand what happened, as I think I tried to do basically the same as you did, but could not see it working ...
question:
    virtual bool has_set_seed() const override final
    {
        return has_set_seed_impl(m_value);
    }
this masses m_value as a const reference to has_set_seed_impl ?
Francesco Biscani
@bluescarni
May 10 2016 19:41
yes, every time you reference a class member in a const method makes it const
Dario Izzo
@darioizzo
May 10 2016 19:42
so, why pagmo::has_set_seed<U>::value,int>::type is true when U is a const ref ?
Francesco Biscani
@bluescarni
May 10 2016 19:42
let's follow the chain
Dario Izzo
@darioizzo
May 10 2016 19:42
lets
:)
Francesco Biscani
@bluescarni
May 10 2016 19:43
let me fetch the old version of the code a moment
otherwise I confuse myself :)
so there were a few things intertwined, but I am gonna focus on one which was the sneakiest
    virtual bool has_set_seed() const override final
    {
        return has_set_seed_impl(m_value);
    }
so this was a const method, which makes the m_value in there a const
The implementation function is:
    template <typename U, typename std::enable_if<pagmo::has_set_seed<U>::value,int>::type = 0>
    static bool has_set_seed_impl(U &p)
    {
       return true;
    }
so the problem here was: what is U?
U gets deduced to const something
Dario Izzo
@darioizzo
May 10 2016 19:47
ah, got it
by putting const U &p you make U deconstized
Francesco Biscani
@bluescarni
May 10 2016 19:48
yeah exactly
Dario Izzo
@darioizzo
May 10 2016 19:48
one last curiosity then, why did the inventory pass the test instead?
Francesco Biscani
@bluescarni
May 10 2016 19:48
this is something I had noticed already in the problem code, but it was not a problem because all the methods we required were const
which test?
Dario Izzo
@darioizzo
May 10 2016 19:49
in the old code (see above) building a problem{inventory} would correctly detect is stochastic etc .
the snippet I posted before typing "any ideas"?
That sent me completely offguard ... it made no sense to me.
notice the round brackets vs square brackets
Dario Izzo
@darioizzo
May 10 2016 19:52
:) yes but the seed is correctly set
ok got it .... there is no way I could have implemented this correctly
Francesco Biscani
@bluescarni
May 10 2016 19:53
well the extra info is taken directly from the concrete problem
which makes no use of problem's methods
Dario Izzo
@darioizzo
May 10 2016 19:54
and the seed was set correctly as set seed was functioning
need to go now to the airport ...
sorry for the mess .... no way I could avoid it :(
Francesco Biscani
@bluescarni
May 10 2016 19:54
no problem it was tricky
took me a moment to get it
are you around lateR?
Dario Izzo
@darioizzo
May 10 2016 19:55
not sure ... I need to go to schipol and wait, may be back too late
will try ...
Francesco Biscani
@bluescarni
May 10 2016 19:55
ok have fun :)
Marcus Märtens
@CoolRunning
May 10 2016 20:13
What is the reason to write loops like for (decltype(M) i = 0u; i < M; ++i) { ... }?
Francesco Biscani
@bluescarni
May 10 2016 20:14
to make sure that the loop variable i is the same as the M variable
the types I mean
Marcus Märtens
@CoolRunning
May 10 2016 20:15
but isn't i not implicitly an unsigned int when setting it = 0u?
Francesco Biscani
@bluescarni
May 10 2016 20:15
there are various unsigned types, unsigned int, unsigned long, unsigned char, etc.
if I recall correctly, that M is coming out from a vector size
Marcus Märtens
@CoolRunning
May 10 2016 20:17
correct
Francesco Biscani
@bluescarni
May 10 2016 20:18
and the standard guarantees only that vector sizes are "some unsigned integral type"
Marcus Märtens
@CoolRunning
May 10 2016 20:18
auto M = input_f[0].size();
Francesco Biscani
@bluescarni
May 10 2016 20:19
right... typically that will bee std::size_t, which in turn is typically unsigned long or unsigned long long
it depends on the platform
but the correct way of doing it is to use exactly the same type, whatever it is
Marcus Märtens
@CoolRunning
May 10 2016 20:20
Okay - I try not to let this confuse me too much...
Francesco Biscani
@bluescarni
May 10 2016 20:20
you'll get used to it :)
if you don't need explicitly the index i, you can just do for (const auto &x: vector) and forget about it
Marcus Märtens
@CoolRunning
May 10 2016 20:23
I am afraid, I will need it. I have to loop through a vector of points kinda orthogonal...
so dimension-wise instead of point-wise
Francesco Biscani
@bluescarni
May 10 2016 20:24
if it makes you feel better you can place this on top of your routine: using size_type = decltype(input_f[0].size()) and then do for (size_type i = 0; i < M; ++i) throughout
I mean at the beginning of the routine code
(not outside it)
Marcus Märtens
@CoolRunning
May 10 2016 20:26
No... I guess I stick to the pattern. So decltype basically infers the type from whatever you throw in and auto refers the type from whatever is supposed to be returned by definition?
Francesco Biscani
@bluescarni
May 10 2016 20:27
yes, they are similar... but auto you use it only in the variable declaration
you could also do something like decltype(input_f[0].size()) M = input_f[0].size()
but that would be a bit redundant :)
so auto is better here
there are more subtle differences between decltype and auto, but you need to be aware of them only when you are dealing with references
Marcus Märtens
@CoolRunning
May 10 2016 20:29
but auto would not work in the for loop from above
or would it?
Francesco Biscani
@bluescarni
May 10 2016 20:29
that's correct - auto deduces the type from the right hand side of the assignment, and if you do auto i = 0u i is then deduced as unsigned int
auto i = 0 is deduced as int
auto i = 0L is deduced as long
etc.
Marcus Märtens
@CoolRunning
May 10 2016 20:31
subtle! :worried:
Francesco Biscani
@bluescarni
May 10 2016 20:31
it is not really specific to auto though... 42 has always been a literal constant of type int
Marcus Märtens
@CoolRunning
May 10 2016 20:38
can I do a "sliced"-loop somehow? For example: for (auto p : m_points) but starting at m_points[1] instead of m_points[0]?
Francesco Biscani
@bluescarni
May 10 2016 20:41
not out of the box with the auto syntax I am afraid, though it should be easy to write a small helper class for that... so that you could do:
for (const auto &p: from_index(m_points,1)) {
Marcus Märtens
@CoolRunning
May 10 2016 20:46
I used indices now
My function works so far
Marcus Märtens
@CoolRunning
May 10 2016 20:51
    vector_double get_refpoint(const double offset = 0.0) const {
        // Corner case
        if (m_points.size() == 0u) {
            return {};
        }

        auto fdim = m_points[0].size();
        vector_double ref_point(m_points[0].begin(), m_points[0].end());

        for (decltype(fdim) f_idx = 0u; f_idx < fdim; ++f_idx) {
            for (std::vector<vector_double>::size_type idx = 1; idx < m_points.size(); ++idx) {
                ref_point[f_idx] = std::max(ref_point[f_idx], m_points[idx][f_idx]);
            }
        }

        for (auto &c : ref_point) {
            c += offset;
        }

        return ref_point;
    }
Could this be improved somehow? It feels a bit dumb...
Its supposed to find the maximum coordinate in each dimension of a vector of points.
And giving it an offset
Francesco Biscani
@bluescarni
May 10 2016 20:55
I don't see anything wrong with it
Marcus Märtens
@CoolRunning
May 10 2016 20:56
Okay, cool :)

Another fairly basic questions: should it be

const std::vector<vector_double> get_points() const
    {
        return m_points;
    }

Or would const std::vector<vector_double> &get_points() const be better? The latter gives a reference while the first would copy the points, correct?

Francesco Biscani
@bluescarni
May 10 2016 21:00
so in general you never want to put a const on the return type, if it is not a reference
that is a method which returns an internal data member right?
Marcus Märtens
@CoolRunning
May 10 2016 21:01
correct
Francesco Biscani
@bluescarni
May 10 2016 21:02
returning a reference performs better as you do not need to make a copy and allocate memory
but it gives you some extra cognitive load, as when you get that reference out you must make sure that you never use it after the originating class has been destroyed
I prefer the const reference usually
you can always get a copy from the const reference if you need it
Marcus Märtens
@CoolRunning
May 10 2016 21:04
the const reference will not allow you to change the internal data-member m_points, right?
Francesco Biscani
@bluescarni
May 10 2016 21:04
that is correct
Marcus Märtens
@CoolRunning
May 10 2016 21:04
What about get_refpoint? This one gives not a reference, but constructs a vector... however a const one. Does the const-return type make sense in that function?
Francesco Biscani
@bluescarni
May 10 2016 21:05
I would not use it, because it does not give you much.. what is the motivation for marking the return value as const?
Marcus Märtens
@CoolRunning
May 10 2016 21:07
Well, the idea is that you use this point as a reference point for hypervolume computations. If you do not want to construct a reference-point by this method, you can define your own reference point. So why would you want to mingle with what the method returns to you? The only reason is to offset the coordinates, but this you can do by the parameter.
Not sure this is a good reasoning though.
This whole const-business is something I never quite understood, hence all these questions :)
Francesco Biscani
@bluescarni
May 10 2016 21:09
I don't find much value in restricting what the user can do with the return value, in the sense that you can write const auto ref_point = get_refpoint(...) and achieve the same effect
I am not totally sure of how const works on return values though as it is something I've rarely seen used
it seems they also inhibit move semantics, which is not so good in C++11
Marcus Märtens
@CoolRunning
May 10 2016 21:12
so basically almost never a good idea
Francesco Biscani
@bluescarni
May 10 2016 21:13
yeah
Marcus Märtens
@CoolRunning
May 10 2016 21:13
so if you return by value, you do not have a const return
if you return by reference it depends whether you want the reference to be used to change the object, right?
Francesco Biscani
@bluescarni
May 10 2016 21:14
yes.. returning a reference has 2 goals: performance and allowing you to change the internal value of a class
Marcus Märtens
@CoolRunning
May 10 2016 21:14
So by returning const reference I protect my internal member m_points from being changed (which could lead to some inconsistency for example, as m_points have to obey certain constraints)
Francesco Biscani
@bluescarni
May 10 2016 21:14
although it could be argued that once you have a method that just returns a non-const reference, you might as well just expose the member as public as there's effecitvely no difference
yes
Marcus Märtens
@CoolRunning
May 10 2016 21:16
Okay... syntax for const reference is const int &i() { return m_i; }
Francesco Biscani
@bluescarni
May 10 2016 21:17
yeps
Marcus Märtens
@CoolRunning
May 10 2016 21:17
The one thing that always confuses me: what does the second const mean?
Francesco Biscani
@bluescarni
May 10 2016 21:17
which second const?
Marcus Märtens
@CoolRunning
May 10 2016 21:17
const int &i() const { return m_i; }
Francesco Biscani
@bluescarni
May 10 2016 21:17
ah ok... that means that the method can be called only from const instances of the class
well not exactly, let me rephrase.. a non-const method cannot be called on const instances of the class
but you can call const-methods on non-const instances of the class
if it makes any sense
:)
example:
void foo() const
{}
void bar()
{
    foo(); // this is legal
}
void baz() const
{
    bar();
}
this will give a compilation error, because bar() is a non-const method
essentially, const methods cannot modify the state of the class, either by modifying its data members or by calling non-const methods
you should mark any method which does not modify the class as const
Francesco Biscani
@bluescarni
May 10 2016 21:22
inside a const method, each time you access a member of the class, a const is implicitly added to the member of the class
example:
struct my_struct
{
    void foo() const
    {
        std::cout << m_value << '\n'; // This is ok, as the stream operator accepts const references as arguments
        m_value += 1; // This is NOT ok, you cannot add to a const int
   }
   int m_value;
};
so for instance if you were to write your get_points() getter as this:
const vector_double &get_points()
{
    return m_points;
}
this would not work because m_points in that method is a non-const entity
because it's used from a non-const method
so that's why you always write getters in pairs like this:
// The const getter.
const vector_double &get_points() const
{
    return m_points;
}
// The mutable getter.
vector_double &get_points()
{
    return m_points;
}
Marcus Märtens
@CoolRunning
May 10 2016 21:27
:worried:
Okay, wait... let me parse this information.
Francesco Biscani
@bluescarni
May 10 2016 21:28
sorry was missing a bit
Marcus Märtens
@CoolRunning
May 10 2016 21:28
okay... m_points is mutable
it is non-const
Francesco Biscani
@bluescarni
May 10 2016 21:29
you mean it is declared as non-const data member?
Marcus Märtens
@CoolRunning
May 10 2016 21:29
it is declared without const
Francesco Biscani
@bluescarni
May 10 2016 21:29
yes that's good
it still becomes a const entity when used from within a const method
Marcus Märtens
@CoolRunning
May 10 2016 21:30
I am still puzzled why const vector &get_points would not work?
Francesco Biscani
@bluescarni
May 10 2016 21:31
that would work :)
so it means you understood correctly
but it confounds a bit the intent of the getter
Marcus Märtens
@CoolRunning
May 10 2016 21:31
:unamused:
Okay, true
The getter shall give you a const reference
so you can access the m_points but not change them
This is done by the first const
So why would I want to add the second const?
Francesco Biscani
@bluescarni
May 10 2016 21:33
it helps once you understand how methods are implemented under the hood. Your const getter is syntactic sugar for the plain function
const vector_double &get_points(const class *this)
{
    return this->m_points;
}
the pointer to the calling class, this, is always passed as implicit first argument of any method
the const at the end of the method declaration tells you wheter the passed this pointer is const or not
So why would I want to add the second const?
Marcus Märtens
@CoolRunning
May 10 2016 21:35
Ah... I could do stuff like this->m_points = nullptr;
But since it is const
I can't
Francesco Biscani
@bluescarni
May 10 2016 21:36
so the reason you need to have both versions of the getter is the following
what's the name of the class?
Marcus Märtens
@CoolRunning
May 10 2016 21:36
the class is hypervolume
Francesco Biscani
@bluescarni
May 10 2016 21:37

ok so:

hypervolume hv;
hv.get_points();

which one of the two overloads should be called?

the mutable or the const getter?
Marcus Märtens
@CoolRunning
May 10 2016 21:37
mhh... good question
well, hv is not const
Francesco Biscani
@bluescarni
May 10 2016 21:38
since the object hv is not const, the non-const get_points() would be called
exactly
but you have 2 non-const get_points()
and they differ only on the return type
this is an ambiguity and it will not compile
Marcus Märtens
@CoolRunning
May 10 2016 21:39
hang on
which 2 non-const do I have exactly?
Francesco Biscani
@bluescarni
May 10 2016 21:39
I thought you had 2 get_points() methods?
if you have only one it will work
Marcus Märtens
@CoolRunning
May 10 2016 21:40
In the code I have right now
I only have one getter, which is const std::vector<vector_double> &get_points() const { ... }
I just try to understand what the different const keywords mean. The first one I get so far... it prevents modification to whatever the reference is pointing at.
The second const means that this method itself does not modify internal members like m_points
At least that is my understanding now
Francesco Biscani
@bluescarni
May 10 2016 21:42
yes that is correct
Marcus Märtens
@CoolRunning
May 10 2016 21:43
But still... it is a getter I mean... I could omit the second const and nothing would change?
Now you tell me, that if I would make a const instance of hypervolume
I could no longer call the getter
Francesco Biscani
@bluescarni
May 10 2016 21:44
yes exactly
Marcus Märtens
@CoolRunning
May 10 2016 21:44
unless I declare the getter with the second const
Francesco Biscani
@bluescarni
May 10 2016 21:45
yup yup
Marcus Märtens
@CoolRunning
May 10 2016 21:45
which is interesting, as I was not aware that the interface of a const object could look potentially much different than that of a non-const object :)
Francesco Biscani
@bluescarni
May 10 2016 21:46
in which sense would it be different?
Marcus Märtens
@CoolRunning
May 10 2016 21:46
In the sense that it would not provide certain methods... but I guess that makes sense.
So you would not have the setter i.e.
Francesco Biscani
@bluescarni
May 10 2016 21:47
right ok
Marcus Märtens
@CoolRunning
May 10 2016 21:47
which has no const keyword at all
What I did not understand: what was the ambiguity you were talking about?
So in theory I could have two different getters
one const and one non-const
for a const-object
There would only be the const-getter available
but for a non-const object... there would be two
correct?
Francesco Biscani
@bluescarni
May 10 2016 21:48
the ambiguity is in general when you have two methods with identical signatures, excluding the return type
so if you have two methods:
void foo() {}
int foo() {}
and you call class.foo() this will be ambiguous
Marcus Märtens
@CoolRunning
May 10 2016 21:51
true
So that is just not possible - compile error
Francesco Biscani
@bluescarni
May 10 2016 21:51
yes
Marcus Märtens
@CoolRunning
May 10 2016 21:52
Oh boy
:smile:
Marcus Märtens
@CoolRunning
May 10 2016 22:23
boost::shared_ptr is no longer in use, right? What is the substitute?
Francesco Biscani
@bluescarni
May 10 2016 22:24
std::shared_ptr, #include <memory>
Marcus Märtens
@CoolRunning
May 10 2016 22:27
okay
Marcus Märtens
@CoolRunning
May 10 2016 22:49
is there an equivalent for boost::lexical_castas well?
Francesco Biscani
@bluescarni
May 10 2016 22:49
dario likes std::to_string, but that will only work for integrals and floating point as far as I know
Marcus Märtens
@CoolRunning
May 10 2016 22:51
That is sufficient
Francesco Biscani
@bluescarni
May 10 2016 23:22
Marcus Märtens
@CoolRunning
May 10 2016 23:24
yay! :+1: