Is there a template debugger? - c++

Templates can be programs in themselves.
Is there a template debugger so you can step thru the "execution" of the template?
This would basically have to be something that is done during compile/link/codegen - and is distinct from debugging the generated program.
Even in many "primitive" environments where you cannot use a debugger, you can usually do "printf debugging". Is even that possible with templates?
edit: Another way to think about this is something like the C preprocessor. It is often very useful to generate "preprocessed" source code - the output from the preprocessor that the compiler is actually compiling - this lets you see what effect your macros are having. A template equivalent would be great - have the compiler output the non-template source code which cooresponds to the templated input. The closest you can get I suppose is a C++ to C translator. (Doesn't the comeau compiler do this?)

You might want to look at this patch for clang that outputs template instantiations.
Another simple tool is the error messages your compiler produces for attempting to instantiate an undefined template.
template< typename > struct TD;
template< typename T >
void your_template_function( T & param )
{
// Both of these produce an error about "undefined type TD< T > with T = ..."
TD< T > test1;
TD< decltype( param ) > test2;
}
This is explained in Scott Meyers CPPCon talk, right after the ring-tailed lemur slide.

On the last years c++ conference there was a talk to that topic. Some of the informations you can find here:
http://gsd.web.elte.hu/contents/articles/gpce06.pdf
and
http://patakino.web.elte.hu/ECOOP_Templight_Poster.pdf
I have no idea how functional that stuff now is, but it was a very interesting startpoint.
I personal wrote me some helper classes which are able to print me the given types like printf debugging for standard code. If the compilation fails it often gives a good error message while calling the DebugPrinter and if the program compiles but the result is really stupid because the type expansion is not what I expect the DebugPrinter helps me a lot!
template< typename T>
int DebugPrintArgs( T arg )
{
std::cout << arg << ", ";
return 0;
}
template <typename Head, typename ... T>
class DebugPrinter: public DebugPrinter<T...>
{
public:
DebugPrinter()
{
std::cout << "--------------------------" << std::endl;
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << "--------------------------" << std::endl;
}
template< typename ...Y>
DebugPrinter( Y ... rest )
{
std::cout << "Construction of: " << __PRETTY_FUNCTION__ << " Values: " ;
ExpandWithConstructor{DebugPrintArgs( rest)...};
std::cout << std::endl;
}
};
template <typename Head>
class DebugPrinter< Head >
{
public:
DebugPrinter()
{
std::cout << "--------------------------" << std::endl;
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << "--------------------------" << std::endl;
}
};

Related

c++ const ref vs template concept

I'm studying the c++20 specifications for templates, in detail the concepts.
Currently for passing parameters to functions I use the const ref:
void writeMsg(const std::string& msg) {
std::cout << "msg = " << msg << "\n";
}
I have only now discovered that templates can also be used, and with concepts I can control the parameters passed. Example:
template<typename T>
concept is_string = std::is_convertible<T, std::string>::value;
template<is_string T>
void writeMsg2(T&& msg) {
std::cout << "msg =" << msg << "\n";
}
Personally I can't understand the benefits, maybe my case is wrong to get the benefits from the concepts? Do you have any suggestions or links to help me in this question?
Thanks
As you presented it: types which are convertible to std::string wouldn't need to be converted before the call to std::cout (potentially saving memory [de]allocations).
It's the only big advantage I can see looking at your code. However, flipping a bit or two:
template <class T>
concept String = std::is_convertible<T, std::string>::value;
void writeMsg2(String auto const& msg) {
std::cout << "msg = " << msg << "\n";
}
Live on Compiler Explorer

Why are variable types that appear the same not being recognized as the same?

I really don't know what to do with this. It seems code is behaving differently depending on where a variable (or its type) originates. And I don't know how to work around this to get consistent behavior.
Below (and linked) is a distilled version of some code being developed for fmtster.
In this code, specialized structures are created for a specific types (float and std::string in the example). Some member functions in the templatized structures (not shown in the example) are then called by the framework ({fmt} or std::format).
is_foobar_v<> is designed to check whether, for the specified type, there is a specialization of the foo structure which has bar as its base class. When the specific type is used as the template argument, it works correctly. Also, when decltype() is used with the local variables, it also works correctly:
is_foobar_v<int> returns false, because foo<int> does not use bar as a base class
is_foobar_v<float> returns true, because foo<float> does use bar as a base class.
is_foobar_v<string> returns true, because foo<string> does use bar as a base class.
(Clearly use of decltype() is not an issue.)
However, next in the code is one example from two places where is_foobar_v<> fails. The code below steps through the elements of a tuple<>, checking whether a foo<> structure, using that type as the template argument, is based on bar. is_foobar_v<> always returns false.
Note that I've also added an explicit instantiation of foo<> objects, to show which constructors are called. You'll note that these logs show that the code does not instantiate the proper specialization inside the lambda. Oddly, in the actual code, the instantiation actually works correctly, even though my check fails. However, I was not able to figure out why it fails to instantiate the correct specialization structure in this distilled code. After most of a day wasted trying, I'm hoping that is not related to the check failure.
I want to reiterate that this is one of two places where I have encountered this. The other was in a simpler templated member function calling a visitor function, and it was not related to the tuple<> loop and it did not use a lambda. In that case, I was able to work around the problem because the type in question was available explicitly as a template parameter (or more specifically as a type trait of a template parameter (i.e. T::value_type)).
That workaround is not available here.
Also, as I mentioned, in the actual code, the correct specialization is being created. So there, I also tried to check whether a function that only exists in the bar equivalent is present. I tried the code snippet below the test program, which also didn't work. And I tried to actually instantiate a foo<> object and then dynamic_cast<> its pointer to a bar pointer, which I would check for nullptr. But in that environment, I don't seem to be allowed to create the foo<> object explicitly.
Anyway, on to the code:
Code on godbolt.org
#include <iostream>
using std::cout;
using std::endl;
using std::boolalpha;
#include <string>
using std::string;
#include <tuple>
using std::make_tuple;
// template argument iteration for std::tuple<>
template<typename F, typename... Ts, std::size_t... Is>
void ForEachElement(const std::tuple<Ts...>& tup,
F fn,
std::index_sequence<Is...>)
{
(void)(int[]) { 0, ((void)fn(std::get<Is>(tup)), 0)... };
}
template<typename F, typename...Ts>
void ForEachElement(const std::tuple<Ts...>& tup, F fn)
{
ForEachElement(tup, fn, std::make_index_sequence<sizeof...(Ts)>());
}
template<typename T>
struct foo
{
foo() { cout << "foo::foo<>()" << endl; }
};
struct bar
{
bar() { cout << "bar::bar()" << endl; }
};
template<>
struct foo<float> : public bar
{
foo() { cout << "foo::foo<float>()" << endl; }
};
template<>
struct foo<string> : public bar
{
foo() { cout << "foo::foo<string>()" << endl; }
};
template<typename T>
inline constexpr bool is_foobar_v = std::is_base_of_v<bar, foo<T> >;
int main()
{
int i;
float f;
string s;
foo<int>();
cout << "foo<" << typeid(int).name() << "> "
<< (is_foobar_v<int> ? "IS" : "is NOT")
<< " a child of bar" << endl;
foo<float>();
cout << "foo<" << typeid(float).name() << "> "
<< (is_foobar_v<float> ? "IS" : "is NOT")
<< " a child of bar" << endl;
foo<string>();
cout << "foo<" << typeid(string).name() << "> "
<< (is_foobar_v<string> ? "IS" : "is NOT")
<< " a child of bar" << endl;
foo<decltype(i)>();
cout << "foo<" << typeid(i).name() << "> "
<< (is_foobar_v<decltype(i)> ? "IS" : "is NOT")
<< " a child of bar" << endl;
foo<decltype(f)>();
cout << "foo<" << typeid(f).name() << "> "
<< (is_foobar_v<decltype(f)> ? "IS" : "is NOT")
<< " a child of bar" << endl;
foo<decltype(s)>();
cout << "foo<" << typeid(s).name() << "> "
<< (is_foobar_v<decltype(s)> ? "IS" : "is NOT")
<< " a child of bar" << endl;
auto tup = make_tuple(i, f, s);
ForEachElement(
tup,
[](const auto& elem)
{
foo<decltype(elem)>();
cout << "foo<" << typeid(elem).name() << "> "
<< (is_foobar_v<decltype((elem))> ? "IS" : "is NOT")
<< " a child of bar" << endl;
});
}
The output looks like this:
foo::foo<>()
foo<i> is NOT a child of bar
bar::bar()
foo::foo<float>()
foo<f> IS a child of bar
bar::bar()
foo::foo<string>()
foo<NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE> IS a child of bar
foo::foo<>()
foo<i> is NOT a child of bar
bar::bar()
foo::foo<float>()
foo<f> IS a child of bar
bar::bar()
foo::foo<string>()
foo<NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE> IS a child of bar
foo::foo<>()
foo<i> is NOT a child of bar
foo::foo<>()
foo<f> is NOT a child of bar
foo::foo<>()
foo<NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE> is NOT a child of bar
Another thing I tried:
template<typename T>
constexpr bool HasBarBaseHelper()
{ return false; }
template<>
constexpr bool HasBarBaseHelper<bar>()
{ return true; }
template<typename T>
constexpr bool HasBarBase()
{ return HasBarBaseHelper<fmt::formatter<T> >(); }
...
if (HasBarBaseHelper<foo<decltype(elem)> >())
{
...
I really don't understand why the check succeeds with decltype() of some variables, but not others. And as you can see by the output, the types appear to be exactly the same.
Any help appreciated.
Rick

how to return a reference to a default value of a non-type template argument

I have done a lot of research on this but I wasn't able to find a design pattern addressing the problem. This is a minimal description of what I'm trying to perform.
#include <iostream>
using namespace std;
template <class T, T default_value=T{}>
class A{
private:
T inclassValue;
public:
A(T icv):inclassValue{icv}{}
const T& operator[](int k){
if(k==1) return inclassValue;
return default_value;
}
};
struct two_int{int x;int y;};
int main(){
A<int> a{4};
cout << "a[0]=" << a[0] << endl;
cout << "a[1]=" << a[1] << endl;
/*
A<two_int> b{{3,5}};
cout << "b[0]=" << b[0].x << "," << b[0].y << endl;
cout << "b[1]=" << b[1].x << "," << b[1].y << endl;
*/
return 0;
}
The code will compile, link and output as expected
a[0]=0
a[1]=4
The compiler complains though and issues a warning for the line of code where default_value is used
return default_value;//Returning reference to local temporary object
which makes some sense. Uncommenting the last part in main and compiling, the compiler issue this time an error while building the template
template <class T, const T default_value= T{}>//A non-type template parameter cannot have type 'two_int'
while what I ideally hope for is
b[0]=0,0
b[1]=3,5
I was able to come up with a solution by adding an extra helper class, that will provide the default_value of T (as a static member), to the template arguments. I'm not convinced by the robustness of my trick and I was wondering if there exists a design pattern addressing this. The warning for types and the error for non-types. Also, I shall add that my primary goal is to be able to provide default_value at will (6 for int for example instead of 0).
Thanks
Not exactly sure what you're looking for, but perhaps a static helper finishing for creating a static default T could be useful:
template <typename T>
static const T& default_value() {
static const T* t = new T{};
return *t;
}
Note this will construct T at most once even across threads (in c++11), but still never destruct T. Since it's static, it's likely the lack of destruction is acceptable, but this of course depends on T.
Here is one version that forwards arguments to the constructor of a default_value stored as constexpr. You are quite limited here as to what is valid to pass as arguments (not sure exactly how limited) so it will depend on your use-case.
#include <iostream>
using namespace std;
template <class T, auto... Args>
class A{
private:
T inclassValue;
constexpr static T default_val = T{Args...}; // Changed to curly brackets here
public:
constexpr A(T icv):inclassValue{icv}{}
const T& operator[](int k){
if(k==1) return inclassValue;
return default_val;
}
};
struct two_int{int x;int y;};
int main(){
A<int> a{4};
cout << "a[0]=" << a[0] << endl;
cout << "a[1]=" << a[1] << endl;
A<two_int> b{{3,5}};
cout << "b[0]=" << b[0].x << "," << b[0].y << endl;
cout << "b[1]=" << b[1].x << "," << b[1].y << endl;
return 0;
}

Where and When should we use compile time macro concatenation?

I've seen this bit of code which I thought was great because it saved me from re-writing getter member functions.
#define GET(n_,N_) \
template<typename T> \
const T &get##N_() const \
{ \
return n_; \
} \
From what I know, Macros "write" code at compile time, therefore injecting the function template inside each class and because it's a template, it can compensate for any type.
So I ended up with this:
class Foo
{
int m_a;
GET(m_a,A)
};
then I used like this:
std::cout<< foo->getA<int>() <<std::endl;
My question is, WHEN and WHERE should we use macro templates?
And is there a way to NOT to specify the type when you are calling the getA member function? Is this because it's in a different namespace?
I'm going to suggest that mixing macros and templates will cause you to wind up with the weak points of both, as you've observed. The template return type of a function can never be inferred so you would always have to specify it. BUT luckily there's a solution, and it involves spelling the type into your macro:
#define GETTABLE_ATTR(type, name) \
private:
type name_; \
public:
type get_##name() const \
{ \
return name_; \
}
Whether using this macro is a good idea is still subjective - remember that you only write code once, and you're best served by writing it in the way that will both prevent mistakes as you write it AND will make maintaining the code easiest.
As also speaking for c++14 there are still needs for having c macros involved.
I have two really often used macros in combination with MTP to get a a compile time constant which tells me if a method or attribute is existing in a class. This simply needs the name of the function which can not be given as parameter to a template. So I prepared that inside a c macro which "writes" my template which then can be used inside enable_if clause.
I personally dislike your idea from "automated getters", but this is only a question of taste.
As always in programming: If the thing helps, is not "undefined behaviour", is well documented in the code and could NOT be done with a more strait forward way the use of c macros is allowed. For me c macros are a kind of "self-defence" for not integrated language features.
Another popular example is enumeration with associated text for some kind of reflection or for serialisation.
The example to catch the existence of a method:
#define DECLARE_HAS_METHOD_FULL_SIGNATURE(NAME) \
template<typename, typename T>\
struct has_method_full_signature_ ## NAME {\
static_assert(\
std::integral_constant<T, false>::value,\
"Second template parameter needs to be of function type.");\
};\
\
\
template<typename C, typename Ret, typename... Args>\
struct has_method_full_signature_ ## NAME <C, Ret(Args...)> {\
template<typename T>\
static constexpr auto check(T*)\
-> typename\
std::is_same<\
decltype( std::declval<T>(). NAME ( std::declval<Args>()... ) ),\
Ret \
>::type; \
\
template<typename>\
static constexpr std::false_type check(...);\
\
using type = decltype(check<C>(0)); \
static constexpr bool value = type::value;\
}
EDIT: add some example code how to use this c-macro stuff here.
#include <utility>
#include <iostream>
#include "component/mytypes_traits.h"
DECLARE_HAS_METHOD_PARMS_ONLY(funny);
DECLARE_HAS_METHOD_FULL_SIGNATURE(f1);
DECLARE_HAS_METHOD_FULL_SIGNATURE(f2);
DECLARE_HAS_METHOD_FULL_SIGNATURE(f3);
class A { public: void funny() {} };
class B { public: void dummy() {} };
class C
{
public:
int f1(int) { return 1;}
float f2(int,int) {return 2.0;}
int f3() { return 1;}
};
int main()
{
std::cout << has_method_parms_only_funny<A>::value << std::endl;
std::cout << has_method_parms_only_funny<B>::value << std::endl;
std::cout << "--" << std::endl;
std::cout << has_method_full_signature_f1< C, int()>::value << std::endl;
std::cout << has_method_full_signature_f1< C, int(int)>::value << std::endl;
std::cout << has_method_full_signature_f1< C, int(int,int)>::value << std::endl;
std::cout << "--" << std::endl;
std::cout << has_method_full_signature_f2< C, float()>::value << std::endl;
std::cout << has_method_full_signature_f2< C, float(int)>::value << std::endl;
std::cout << has_method_full_signature_f2< C, float(int,int)>::value << std::endl;
std::cout << "--" << std::endl;
std::cout << has_method_full_signature_f3< C, int()>::value << std::endl;
std::cout << has_method_full_signature_f3< C, int(int)>::value << std::endl;
std::cout << has_method_full_signature_f3< C, int(int,int)>::value << std::endl;
std::cout << "--" << std::endl;
}

C++ making a console: binding a function

I am currently working on creating a console in c++. I have created a class to help link variables and functions in code to variables and functions in the console.
I currently have it set where if I have a variable in code, I can redefine it under the new class and it will be visible to the console. The variable in code still behaves the same as before.
Example:
float var = 1.0;
can be redefined as
ConsoleVar var("myVariable")<float> = 1.0;
var is the variable name in the code and myVariable is the name that you use to access it in the terminal
My question is:
How can I bind a function, or more specifically, detect the number and type of the arguments.
I know that I can template the ConsoleVar class to a void * type to store a function but is there a way for me to auto detect the return type, number of arguments and type of arguments? I am planning on shipping this in a library so I am going for ease of use. If this is possible, I would really like to know (I'll even do assembly if needed) otherwise I have some ideas on how to implement it.
EDIT: So I think that I have a solution but I have a question... Is it possible to pass a variable number of arguments to a function. Not like varargs.
For instance: I recieve 3 args from the command line, now I execute the function
func(arg[1], arg[2], arg[3])
Is it possible to send a variable number of arguments?
This pattern will do the job.
#include <typeinfo>
// Function with 0 parameters
template< typename Ret >
void examine_function( Ret (*func)() )
{
std::cout << typeinfo(Ret).name() << std::endl;
}
// Function with 1 parameters
template< typename Ret, typename Param1 >
void examine_function( Ret (*func)(Param1) )
{
std::cout << typeinfo(Ret).name() << std::endl;
std::cout << typeinfo(Param1).name() << std::endl;
}
// Function with 2 parameters
template< typename Ret, typename Param1, typename Param2 >
void examine_function( Ret (*func)(Param1, Param2) )
{
std::cout << typeinfo(Ret).name() << std::endl;
std::cout << typeinfo(Param1).name() << std::endl;
std::cout << typeinfo(Param2).name() << std::endl;
}