Use template parameter type inside #define - c++

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.

Related

Build time optimization using extern templates

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

How to let users of MyClass, control which version of the class is instantiated by means of a compiler flag?

I have a C++ class that runs in time-sensitive code, such that merely constructing the object may take more time than users can spend. I'd like to define both a standard and a trivially-constructible version of my class, and let users of the class control which version of the class is instantiated by means of a compiler flag. I'd like the compiler flag to work at the level of a group. For example, if the flag were LEVEL=:OFF,GROUP1:ON, then the trivial version would be constructed for all instances of the class except those in GROUP1, which would get the actual, non-trivial instantiation. The goal is for users to be able to turn off certain groups at compile time, by changing the flag value.
I'd like to use C++11's std::conditional to control which version of the class is used. To do this, I need to check the group with which a given usage of the class is associated, and compare it to the compiler flag setting for that group. I can't think of a way for users of the class to pass a compile-time setting to the main class definition from the user's source file. I could require users to put something like #define MYCLASS_GROUP ON in their source file, but I don't think I can reference that in the file where my class is defined.
Is there a way for users of a class to control the compiled version of a class from the user's source file? Thanks in advance for any ideas here!
Update: Here is how I'd ideally like this to be used. A user could do:
#define MYCLASS_GROUP GROUP1
MyClass myClassInstance;
Then, they could control which version is instantiated via a compiler flag. So -DMYCLASS_GROUP_LEVEL=:OFF,GROUP1:ON would enable use cases like the above, in GROUP1.
In the class definition, I'd like something like the following non-working pseudo-code:
class MyClassOn {
non-trivial code here
};
class MyClassOff {
};
typedef std::conditional<check-group-here, MyClassOn, MyClassOff>::type MyClass;
You can use template specialization.
First declare the options:
class DefaultVersion;
class TriviallyConstructible;
Next create the primary template definition of the class
template <typename T = DefaultVersion>
class MyClass;
Specialization for DefaultVersion:
template< >
class MyClass< DefaultVersion >
{
// ...
};
Specialization forTrivially-Constructible version
template<>
class MyClass< TriviallyConstructible >
{
// ...
};
Example of usage
MyClass<> m1;
MyClass< DefaultVersion > m2; // same as m1
MyClass< TriviallyConstructible > m3;
And if the users wants they can declare an alias for this type, which can be used in there application.
How to pass compile time flag to class?
Through preprocessor directives and aliasing.
#ifdef GROUP1 > 0
using MyClassGroup1 = MyClass< TriviallyConstructible >;
#else
using MyClassGroup1 = MyClass< DefaultVersion >;
#endif
Or another way:
#ifdef GROUP1 > 0
using Group1 = TriviallyConstructible;
#else
using Group1 = DefaultVersion;
#endif
and at place of usage
MyClass< Group1 > m4;
#define MYCLASS_GROUP GROUP1
MyClass myClassInstance;
doesn't work. Usually if you need to tweak lib code by preprocessor you define identifier before including lib header.
#define MYCLASS_GROUP GROUP1
#include <MyClass.h>
MyClass myClassInstance;
In MyClass.h you just check what is defined.
In your particular case you don't need preprocessor, as nicely described in Robert Andrzejuk answer.

Group several MPL assertions in a macro

I'm trying to do something like that:
#define VERIFY_EXPECTATIONS \
BOOST_MPL_ASSERT((expectation1)); \
BOOST_MPL_ASSERT((expectation2)); \
BOOST_MPL_ASSERT((expectation3))
and when writing VERIFY_EXPECTATIONS; in line, say 42, I get an error about a conflicting declaration of mpl_assertion_in_line_42.
I understand what is happening (BOOST_MPL_ASSERT uses an identifier that depends on the line where the macro is invoked) but my question is: is there a known workaround to do this kind of things?
Edit:
More precisely, the expectations look like that:
#define TEST_SOME_SET_OF_PREDICATES(Arg) \
BOOST_MPL_ASSERT ((some_predicate<Arg>)); \
BOOST_MPL_ASSERT_NOT((some_other_predicate<Arg>))
TEST_SOME_SET_OF_PREDICATES(some_type);
TEST_SOME_SET_OF_PREDICATES(some_other_type);
I have implemented the predicates and I want to test them with several types.
Note:
I'm not very interested in the following:
template <typename Arg>
struct compound_predicate : boost::mpl::and_<
some_predicate<Arg>,
boost::mpl::not_<some_other_predicate<Arg> >
> {};
BOOST_MPL_ASSERT((compound_predicate<some_type>));
BOOST_MPL_ASSERT((compound_predicate<some_other_type>));
because when an assertion fails, we don't know which of the expectations was wrong.
The solution suggested by Praetorian would be the following:
template <typename Arg>
struct expectations {
BOOST_MPL_ASSERT ((some_predicate<Arg>));
BOOST_MPL_ASSERT_NOT((some_other_predicate<Arg>));
};
and then instantiate expectations with some_type and some_other_type. I would have to implement a macro that declares an object of type expectations<Arg> with a different identifier at each call. It looks a little bit like reimplementing (some part of) static assertions.
Any other ideas?

Is there any way to check whether a function has been declared?

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.

In C++ can one rename/alias a non-namespace, non-class name?

I have
namespace src {
struct src_bar;
void src_baz();
template<class T> class src_qux;
}
which I'd like to reference as
namespace dst {
struct dst_bar;
void dst_baz();
template<class T> class dst_qux;
}
meaning that I'd like to "rename" or "alias" or "relabel" names from src.
For dst_bar one can of course use namespace dst { typedef src_bar dst_bar; }. Is there some (non-macro) equivalent allowing me to rename src::src_baz as dst::dst_baz and src::src_qux as dst::dst_qux?
Unless I'm mistaken, neither a using statement nor a namespace alias can accomplish the other two. Writing templated forwarding functions for dst_baz() is a possibility but requires knowledge of the arity of src_baz. Template typedefs could have dst_qux<T>::type be src_qux<T> but the indirection adds verbosity.
FWIW, my use case is taking C names like somepackage_someportion_somefuncA and providing a namespaced-friendly version somepackage::someportion::somefuncA so that other folks can employ using somepackage::someportion for brevity.
For functions you will have to manually forward the requests. For non-template types you can just typedef. For template types, y can use the new using feature of c++11 To create a typedef-style alias for a template, if your compiler supports it, or else you are basically out of luck.
No, you cannot "rename" something so that it no longer uses its original name.
However, you can get the same effect via trickery.
First, import the header for the defines you want to corral inside a namespace block:
namespace foo {
#include "src_stuff.h"
}
Now you have foo::src::src_bar and friends.
Then, use typedef liberally:
namespace bar {
typedef foo::src::src_bar dst_bar;
}
Voila, you've got a bar::dst_bar which is the same as src::src_bar would have been. If you don't care about the definitions remaining available under the old names in addition, skip the first step and just make typedefs for convenience. That's what they're for, after all.
If usage of macros is an acceptable option for you then here is one solution:
// declare this macro in some common file
#define CREATE(SCOPE) \
namespace SCOPE { \
struct SCOPE## _bar; \
void SCOPE## _baz(); \
template<class T> class SCOPE## _qux; \
}
Usage:
CREATE(src);
CREATE(dst);