4

I'm trying to print the return value of a templated member function in gdb (version 7.6.1 I think) of an rvalue reference, so what I write in gdb amounts to something like this:

gdb> print (*(TypeOne*)var).get<TypeTwo>()

I've tried parenthesizing various parts of the expression with no success, and I wasnt able to find any other question on this. Anyone know?

John Cramerus
  • 159
  • 1
  • 6
  • TypeOne is a wrapper around a std::variant member, the get function just calls std::get on the member. How would I do this with the std::variant member? – John Cramerus Mar 29 '18 at 14:33
  • aparently you should be able to call functions in gdb https://sourceware.org/gdb/onlinedocs/gdb/Calling.html – Raxvan Mar 29 '18 at 14:35
  • You can call functions (although with plenty of caveats) but templates are problematic, with a normal template function you have to encase it in single quotes I think, although I'm by no means a gdb master... – John Cramerus Mar 29 '18 at 14:38
  • An https://stackoverflow.com/help/mcve might get you an answer faster. – Employed Russian Mar 29 '18 at 14:53
  • Possible duplicate of [Debugging C++11 rvalue references with gdb](https://stackoverflow.com/questions/33586045/debugging-c11-rvalue-references-with-gdb) – Mihayl Mar 29 '18 at 14:59
  • Wtf? Me asking how to call a template member function in gdb is a duplicate of how to debug an rvalue reference? – John Cramerus Mar 29 '18 at 15:32

1 Answers1

2

Starting from this related post: How to `print`/evaluate c++ template functions in gdb

I was able to figure out how to do this within my own program. I'm not using an rvalue nor a variant so it may not work for that, but I think it's still relevant to this question.

My use case was a method with a single enum as a template parameter, similar to this:

#include <stdio.h>

enum class MyEnum {
    VALUE_0 = 0,
    VALUE_1 = 1
};

struct TestStruct {
    template <MyEnum VALUE>
    int getValue() {
        if constexpr (VALUE == MyEnum::VALUE_0) {
            return value_0;
        } else /* VALUE == MyEnum::VALUE_1 */ {
            return value_1;
        }
    }
    
    const int value_0 = 7;
    const int value_1 = 9;
};

int main()
{
    TestStruct test;
    test.template getValue<MyEnum::VALUE_0>();
    test.template getValue<MyEnum::VALUE_1>();

    return 0;
}

If we use ptype on the object we get a list of methods on the object:

(gdb) b 36
Breakpoint 1 at 0x4004f7: file main.cpp, line 36.
(gdb) r
Starting program: /home/a.out

Breakpoint 1, main () at main.cpp:36
36          return 0;
(gdb) ptype test
type = struct TestStruct {
    const int value_0;
    const int value_1;
  public:
    int getValue<(MyEnum)1>(void);
    int getValue<(MyEnum)0>(void);
} 

If we want to call this method:

    int getValue<(MyEnum)1>(void);

We can call it by using the name exactly as shown, in single quotes.

(gdb) p test.'getValue<(MyEnum)1>'()                             
$1 = 9

You can try it here: https://onlinegdb.com/7OtaUvK3g

Note from the other thread:

Without an explicit instance in the source code, the compiler will treat the template code as it would "static inline" code and optimize it out if it is unused.

So you must call the method somewhere in your code to be able to call it in gdb at all, this will not work otherwise.

SomeCppDev
  • 21
  • 2