Question about decltype

Two small questions about the use of decltype
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Function:
namespace line {
    inline std::function<Coordinate(double)> path(const Coordinate& start, const Coordinate& end)
    {
        return [=](double t) {
            return (1-t)*start + t*end; //thanks MiiNiPaa
        };
    }
}

int main()
{
    const unsigned Width  = 500;
    const unsigned Height = 500;
    const Coordinate c1(0, 0);
    const Coordinate c2(Width/2, Height);
    const Coordinate c3(3*Width/4, Height/4);

    std::vector<decltype(line::path(c1, c2))> doodle(3);
    // ... assign some paths to the doodle
    render_doodle(doodle);
}

The type of the vector at line 19 is evaluated at compile time due to decltype, correct? So it doesn't waste time at runtime?

And my second question is how would I even write the render_doodle function? I'm at a loss there, should I put some global variable before the function definition? Seems like a bad, confusing practice. Would the compiler be smart enough to know I'm just using some dummy variable to work with decltype?
EDIT: Just tested this
1
2
3
4
void render_doodle(const auto& doodle)
{
    std::cout << "Hiya!" << std::endl;
}

auto, duh... :)
Edit2: Apparently this is only technically allowed in C++14, which isn't a problem, but how would I have done this in only C++11? Would templates be the only option?
Last edited on
C++'s type system happens completely at compile time - at runtime you can only get information about the types you already have.

Also, that second code snippet with the auto parameter is not valid C++14 either.
http://coliru.stacked-crooked.com/a/5f3d61fac663e239
Last edited on
Yes, the type is determined at compile time. Templates have to be instantiated at compile time, which is one of the things decltype is useful for.

As for your render_doodle function, there are a couple of ways. Your 'C++14' (not quite, auto only works like that for lambdas) function is the same is this:
1
2
3
4
template <typename T>
void render_doodle(const T& doodle) {
    std::cout << "Hiya!" << std::endl;
}


As for another way you could do it, the only way I can think of off the top of my head is to put in the actual type of the returning function yourself.
Last edited on
Thanks, I feel like I knew that and have been told it before but still had to be reminded. =) Compilers are amazing to deduce so much stuff at compile time, especially with all that typeid, decltype, and auto stuff.
My favorite header is <type_traits> because it has a solution for almost everything. For example:
http://en.cppreference.com/w/cpp/types/result_of
1
2
3
4
void render_doodle(typename std::result_of<decltype(line::path)>::type const &)
{
    //...
}
(untested, but I am pretty sure it's supposed to work - if not, use std::function<decltype(line::path)>::result_type)
Last edited on
Oh I just saw your edit about it not being valid C++14 either (I hadn't actually tried to compile it under C++14 yet, had only seen the (apparently wrong) warning about it needing C++14 ;p).

Your type_traits code should do the trick, much appreciated.
Edit: I'll try it out now thankfully I have the time.
Last edited on
If it doesn't work see my edited post. I think once I tried to use result_of and I had to use the other approach instead.
There is a way to do it, you need to specify the parameter types as well (in case of overloads):
1
2
3
4
void render_doodle(const typename std::result_of<decltype(line::path)&(const Coordinate&, const Coordinate&)>::type&)
{
    //...
}


Is it just me, or is that incredibly long and messy?

EDIT: For a (simpler) example, look at this: http://coliru.stacked-crooked.com/a/d375de84bb3b71cc
Last edited on
If it doesn't work see my edited post.
Yeah I have my "doodle" as an std::vector of all that stuff and it is giving errors when I try to apply that.
But don't worry, I'll just use the template and read up on type_traits later to see if I can resolve it!

Grateful for both of your times.

Edit: @NT3 yeah that does compile!
And yeah it's incredibly long and messy but hey it works.

________________________

And one more thing, just wanted to say I feel kinda dumb because I got lambdas mixed up with function objects - lambdas need auto but function objects don't, so
 
std::vector<std::function<Coordinate(double)>> doodle(3);

works just fine... :d without having to use decltype. Was good learning experience though :)
Last edited on
Oh yeah, forgot you where using a vector. Gets even worse, now:
1
2
3
4
void render_doodle(const std::vector<std::result_of<decltype(line::path)&(const Coordinate&, const Coordinate&)>::type>&)
{
    // ...
}


I might stick with either the template thing or the actual type of the vector, just because it'd be more readable.
Topic archived. No new replies allowed.