Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to get type of member?

31 views
Skip to first unread message

Philipp Klaus Krause

unread,
Sep 26, 2018, 8:48:37 AM9/26/18
to
How can I get the type of a member of a template parameter. E.g. in a
template <class T_t> assume that T_t has a member x. I want to declare
another variable of the same type.

Philipp

Öö Tiib

unread,
Sep 26, 2018, 9:07:04 AM9/26/18
to
Use decltype specifier.

#include <iostream>

template <typename T_t>
struct Example {
decltype(T_t::x) another; // <--- here
};

// trying out ...

struct Parameter { double x; };

int main()
{
Example<Parameter> test{4.2};
std::cout << test.another << "\n";
}

Philipp Klaus Krause

unread,
Sep 26, 2018, 9:24:54 AM9/26/18
to
Thanks. What if T_t is some boost graph, the vertex type is the struct,
and x is a member of that struct?

Philipp

james...@alumni.caltech.edu

unread,
Sep 26, 2018, 9:41:29 AM9/26/18
to
I'm not familiar with boost graphs, but what expression would you
ordinarily use to access that member of a struct contained in such a
graph? Whatever expression you would use for that purpose, put it inside
the decltype() expression, and it should work.

Öö Tiib

unread,
Sep 26, 2018, 9:49:22 AM9/26/18
to
Basically same. I haven't used Boost.Graph for anything in few years.
When dealing with Boost.Graph use typedefs massively, otherwise you
lose your ways in that <<,><>,<::>::> forest. Something like that:

using Vertex = graph_traits<T_t>::vertex_descriptor;
using X = decltype(Vertex::x);
X another;

Philipp Klaus Krause

unread,
Sep 26, 2018, 9:56:26 AM9/26/18
to
Am 26.09.2018 um 15:49 schrieb Öö Tiib:
>
> using Vertex = graph_traits<T_t>::vertex_descriptor;
> using X = decltype(Vertex::x);
> X another;
>

The vertex_descriptor is not the vertex. From my limited experience,
vertex_descriptor tends to be some unsigned integer type.

Philipp

Öö Tiib

unread,
Sep 26, 2018, 10:20:55 AM9/26/18
to
Then it is vertex_iterator dereferenced or some other such thing.

using VertexIt = graph_traits<T_t>::vertex_iterator;
using Vertex = iterator_traits<VertexIt>::value_type;
using X = decltype(Vertex::x);
X another;

Do not keep your experience so limited. Read docs of stuff you use,
the diagnostics from heavily templated stuff are really lot worse to
read. ;)

Philipp Klaus Krause

unread,
Sep 26, 2018, 10:35:48 AM9/26/18
to
Am 26.09.2018 um 16:20 schrieb Öö Tiib:
> On Wednesday, 26 September 2018 16:56:26 UTC+3, Philipp Klaus Krause wrote:
>> Am 26.09.2018 um 15:49 schrieb Öö Tiib:
>>>
>>> using Vertex = graph_traits<T_t>::vertex_descriptor;
>>> using X = decltype(Vertex::x);
>>> X another;
>>>
>>
>> The vertex_descriptor is not the vertex. From my limited experience,
>> vertex_descriptor tends to be some unsigned integer type.
>
> Then it is vertex_iterator dereferenced or some other such thing.
>
> using VertexIt = graph_traits<T_t>::vertex_iterator;
> using Vertex = iterator_traits<VertexIt>::value_type;
> using X = decltype(Vertex::x);
> X another;

Dereferencing boost vertex iterators yields vertex descriptors, not
vertices.

I don't have much experience with C++ (I prefer C).

So far the only idea I have come up is creating an instance of T_t with
at least one vertex, and then using decltype(T[0].x). But that seemed
too ugly even by C++ standards, so I decided to ask on comp.lang.c++
instead.

Philipp

james...@alumni.caltech.edu

unread,
Sep 26, 2018, 11:26:37 AM9/26/18
to
On Wednesday, September 26, 2018 at 10:35:48 AM UTC-4, Philipp Klaus Krause wrote:
...
> So far the only idea I have come up is creating an instance of T_t with
> at least one vertex, and then using decltype(T[0].x). But that seemed
> too ugly even by C++ standards, so I decided to ask on comp.lang.c++
> instead.

decltype() requires an expression as it's argument. If T is a type, T[0]
could be a typename for an array containing 0 elements of type T - which
would be a problem because of the 0 length. However, the immediately
following '.' would make it a syntax error. A type name can appear in an
expression, but only as the argument of a sizeof, alignof, new, or
typeid expression, never as the the starting portion of the expression.

I think you mean _t[0].x rather than T{0].x. If that's the simplest
expression that you can think of which gives you the value of the x
member, then decltype(_t[0].x) is the best you can do. I'm not sure why
you consider that "too ugly". Any construct that gives you the type of
that member has to be given enough information to identify which member
it is, of which struct type. Could you give an example of less ugly
syntax that could have been used for this purpose (possibly in an
entirely different language from C++), so I can better understand your
judgement of this particular syntax as "too ugly"?

Öö Tiib

unread,
Sep 26, 2018, 11:32:42 AM9/26/18
to
The decltype guarantees that the operand given to it is only
compile time evaluated for type so it must be well-formed approach.
However writing templates around weightiest bits in boost will
take quite lot of stamina and does not really help to learn C++
since that level of work is rather rarely needed.

Usually one uses concrete instantiation of boost.adjacency_list
or the like through pimpl to hide every of its thorns from the
whole world. Not letting anything but one cpp file to #include
that monster tends also to speed the compilation.

Philipp Klaus Krause

unread,
Sep 26, 2018, 11:38:27 AM9/26/18
to
What I meant is

T_t T;
boost::add_vertex(T);
decltype(T[0].x) x;

I consider it ugly because it instantiates an object (T), just to get a
type.

Philipp

Öö Tiib

unread,
Sep 26, 2018, 11:54:54 AM9/26/18
to
> I consider it ugly because it instantiates an object (T), just to get a
> type.

Then don't instantiate.

using Vertex = std::remove_cv<decltype(T_t()[0].x)>::type;

The remove_cv just for case if it returns it const qualified.

james...@alumni.caltech.edu

unread,
Sep 26, 2018, 1:47:00 PM9/26/18
to
On Wednesday, September 26, 2018 at 11:38:27 AM UTC-4, Philipp Klaus Krause wrote:
...
> What I meant is
>
> T_t T;
> boost::add_vertex(T);
> decltype(T[0].x) x;
>
> I consider it ugly because it instantiates an object (T), just to get a
> type.

"The operand of the decltype specifier is an unevaluated operand." (7.1.6.2p4)
0 new messages