For debugging purposes i want to see the result of unpacking variadic templates in c++. Is it possible anyway in VS?
//variadic template
template<class ... Ts>
void foo(Ts...args)
{
//...some code
auto x = bar(args..);
}
//client code:
foo(std::string("123"),int(4),5.6f);
I supposed result of code generation will be unpacked into something like:
void foo<std::string, int, float>(std::string args1, int args2, float args3)
{
//...some code
auto x = bar(args1,args2,args3);
}
But if it`s a little harder, who know what it will unpack into? :)
Before trying to find this i thought that it will be generated during preprocessing if switching "Properties->C/C++->Preprocessor->Preprocess to a File" to Yes in VS we can see this. But not, on this stage it only work with headers, #incldude''s #define''s ...
Question is how to see the result of unpacking parameter packs code generation? Does this code exist in readable form at all ? Or result translated into binary and *.exe file?
What you can do is a kind of static printing.
Static printing that will stop the compilation with an error revealing the params
template <typename...>
struct TParamViewer;
#define DEBUG_PRINT
#ifdef DEBUG_PRINT
#define VIEW_TPL_PARAMS(index, params) TParamViewer<params> td##index;
#else
#define VIEW_TPL_PARAMS(index, params)
#endif
//variadic template
template<class ... Ts>
void foo(Ts...args)
{
VIEW_TPL_PARAMS(0, Ts...);
}
Static printing that will show warnings revealing the params
Here we add a definition to the viewer class that will display a warning revealing the template params.
template <typename...>
struct TParamViewer {
bool i = 10;
};
All these solutions are just trick. In gcc, there is a proposed patch for proper debug printing.
Regards,
Related
I'm trying to optimize my build time using extern templates because I have a lot of generated headers that contain typedefs to a template class.
The template class
// TypeID.h
template <typename T>
class TypeID
{
public:
TypeID(/* <some parameters> */);
bool isNull() const;
// ... many other methods
};
template <typename T>
TypeID<T>::TypeID(/* <some parameters> */)
{
// impl
}
template <typename T>
bool TypeID<T>::isNull() const
{
// impl
}
// same for the rest of the methods
Example of generated header
// NamedID.h
#include "TypeID.h"
typedef TypeID</* some type */> NamedID;
There are many (~2k) headers like NamedID with different types and they're included throughout the project.
I changed the code generator to add this line above the typedef:
extern template class TypeID</* some type */>;
and in addition to the header files, it now also generates a cpp where all the extern templates have a corresponding
template class TypeID</* some type */>;
Due to the number of headers and how many times they're used in the project I expected a big difference in compile time (at least something noticeable) but there's no difference.
I ran several runs of the build with and without this change and all of them take 2h 30m +/-2m.
Did I implement this wrong ? Am I expecting too much ?
My environment:
RHEL 7.7
GCC 8.3.1
CMake + ninja, no ccache, no icecream/distcc
Suppose there's a library, one version of which defines a function with name foo, and another version has the name changed to foo_other, but both these functions still have the same arguments and return values. I currently use conditional compilation like this:
#include <foo.h>
#ifdef USE_NEW_FOO
#define trueFoo foo_other
#else
#define trueFoo foo
#endif
But this requires some external detection of the library version and setting the corresponding compiler option like -DUSE_NEW_FOO. I'd rather have the code automatically figure what function it should call, based on it being declared or not in <foo.h>.
Is there any way to achieve this in any version of C?
If not, will switching to any version of C++ provide me any ways to do this? (assuming the library does all the needed actions like extern "C" blocks in its headers)? Namely, I'm thinking of somehow making use of SFINAE, but for a global function, rather than method, which was discussed in the linked question.
In C++ you can use expression SFINAE for this:
//this template only enabled if foo is declared with the right args
template <typename... Args>
auto trueFoo (Args&&... args) -> decltype(foo(std::forward<Args>(args)...))
{
return foo(std::forward<Args>(args)...);
}
//ditto for fooOther
template <typename... Args>
auto trueFoo (Args&&... args) -> decltype(fooOther(std::forward<Args>(args)...))
{
return fooOther(std::forward<Args>(args)...);
}
If you are statically linking to a function, in most versions of C++, the name of the function is "mangled" to reflect its argument list. Therefore, an attempt to statically link to the library, by a program with an out-of-date .hpp file, will result in an "unknown symbol" linker-error.
In the C language, there's no metadata of any kind which indicates what the argument list of any exported function actually is.
Realistically, I think, you simply need to be sure that the .h or .hpp files that you're using to link to a library, actually reflect the corresponding object-code within whatever version of that library you are using. You also need to be sure that the Makefile (or "auto-make" process) will correctly identify any-and-all modules within your application which link-to that library and which therefore must be recompiled in case of any changes to it. (If it were me, I would recompile the entire application.) In short, you must see to it that this issue doesn't occur.
In C++ you can do something like this:
#include <iostream>
#include <type_traits>
//#define DEFINE_F
#ifdef DEFINE_F
void f()
{
}
#endif
namespace
{
constexpr struct special
{
std::false_type operator()() const;
}f;
}
struct checkForF
{
static const constexpr auto value = std::conditional< std::is_same<std::false_type, decltype(::f())>::value, std::false_type, std::true_type >::type();
};
int main()
{
std::cout << checkForF::value << std::endl;
}
ideone
Please note I only handle f without any parameters.
The context of my situation is pretty hard to explain exhaustively here but : I am using an external toolset (lib, bins, etc.) which generates some c++ code from a proprietary IDL file. For a given type T, it generates a T_Result class. The generated code is then integrated to my project.
Now, I am trying to generate a type based on the type of a template parameter.
#define GENTYPE(x) x ## _Result
// class coming from generated includes. Copied here for clarity.
class int_Result
{};
template < class T >
class Connector
{
GENTYPE(T) _result;
public:
};
int main()
{
Connector<int> t;
/* ... */
}
Of course, this does not work because the c-preprocessor uses the T value as it, so the GENTYPE macro is expanded inside the Connector class as T_Result instead of the wanted int_Result class.
One could use #define to produce the whole class but then very difficult to maintain, debug, etc.
Does anyone knows a trick to achieve this goal ?
Instead of a macro generating Connector, we use a macro to generate a traits class that maps T to T_result. Then Connector just uses that traits class.
template<class T>struct result_type;
#define MRT(T) \
template<>struct result_type<T>{ \
using type = GENTYPE(T); \
}
template<class T>using result_t=typename result_type<T>::type;
now simply do a MRT(int); to make result_t<int> be to int_result. The macro must be used before the first use of result_t<int>. Failure to do MRT(int) makes result_t<int> an error.
This assumes C++11 support: it is 2015.
In Connector just do result_t<T> _result;
Use of MRT is optional, as a strait
template<>struct result_type<int>{ using type=GENTYPE(int); };
or even
template<>struct result_type<int>{ using type=int_result; };
isn't all that verbose, and reduces the number of layers of macros. It does violate DRY (don't repeat yourself) however.
I have an odd issue in MSVS 2010. I have a class with a function that is templitized and contains an parameter with a default value.
In my header file:
typedef unsinged int data32
class myClass
{
private:
...
public:
...
template <typename T>
T* myF(data32);
}
...
template<typename T>
T* myClass::myF(data32 size = 1)
{
...
}
Ok, now in my main i have something like this:
int main()
{
myClass A;
data32* myInt = A.myF<data32>(100); // no complaints from pre-compiler
data32* myInt2 = A.myF<data32>(); // pre-compiler complains "Error: no instance of the function template "myClass::myF" matches the argument list"
}
I understand why it is unhappy as i do not have a function prototype defined for 'myF()' in the class, but shouldn't it know better? I thought the point of defaults were to make the parameters optional in the call. The code DOES compile and run just fine even thought the pre-compiler is unhappy and flags this as a problem.
Any thoughts??
Thanks!
There are bugs (false alarms) in the intellisense analyzer in VS 2010. And this seems like one of them. The analyzer used for intellisense is different from the actual parser used in compiler.
I'm designing a CUDA-C++ library with template classes. There are template functions my classes use, and they are invisible to main as well as the user. I need to specialize them explicitly because of the two steps of compiling to be performed, otherwise I'd get an "unresolved external" error when linking. Being this classes used in main.cpp, there's no way (I guess...) to tell nvcc what types are going to be used in tha main program, so I thought of using some macros to specialize them. Here's a simplified versione of the code:
//CUDA_functions.h
// CUDA functions declared here and included in files that will be compiled
// with g++. Those functions are implemented in .cu files, compiled with nvcc
template <typename T>
void foo1(T x);
template <typename T>
void foo2(T x);
template <typename T>
void foo3(T x);
//fileA.h - included in main.cpp
#include "CUDA_functions.h"
template <typename T>
class A {
// it uses foo1 & foo2 inside
}
//fileB.h - included in main.cpp
#include "CUDA_functions.h"
template <typename T>
class B {
// it uses foo1 & foo3 inside
}
//macros.h
#define _USE_CLASS_A(T) template void foo1(T); \
template void foo2(T); /**/
#define _USE_CLASS_B(T) template void foo1(T); \
template void foo3(T); /**/
//user_spec.cu - template specializations by user. This is the first file to be
// - compiled and it doesn't know what classes are going to be used
// say, user wants to use classes A & B: HERE THE ERROR RAISES!
#include "macros.h"
_USE_CLASS_A( int );
_USE_CLASS_B( int );
When I compile this code with Visual Studio, I get a warning about the double explicit instantiation (foo1), but when I compile it with g++ warning becomes an error!
I can't write macros like
#define _USE_FOO1(T) template void foo1(T) /**/
#define _USE_FOO2(T) template void foo2(T) /**/
#define _USE_FOO3(T) template void foo3(T) /**/
because the user doesn't have to worry about the existence of those functions and I'd like to specialize a list of them based on what class he/she is going to use. Last but not least, I found nothing about a "conditional specialization" of template. What can I do to solve? Thanks to everyone would be so nice to answer. Bye.
Is it for host code or device code? I believe CUDA does not support linking for device code. Linking template functions in host code has always been a bit fishy, CUDA or no CUDA.
Instead of having your hands dirty with macros -- how about putting them in a header, inside of namespace detail?
By convention, detail namespace indicates library internal stuff that you shouldn't ever access as a user.