Templates accepting "anything" in C++ - c++

I have a simple template struct associating a string with a value
template<typename T> struct Field
{
std::string name; T self;
}
I have a function that I want to accept 1-or-more Fields of any type, and the Fields may be of possible different types, so I'm using a std::initializer_list because C++, to my knowledge, lacks typed variadic arguments, cannot determine the size of variadic arguments, and must have at least one other argument to determine where to start.
The problem is that I don't know how to tell it to accept Fields that may be of different types. In Java, I would just use foo(Field<?> bar, Field<?>... baz), but C++ lacks both typed variadic arguments and wildcards. My only other idea is to make the parameter of type
std::initializer_list<Field<void*>>, but that seems like a bad solution... Is there a better way to do it?

A couple of things...
C++11 (which you seem to have since you are talking about std::initializer_list) does have typed variadic arguments, in particular they are named variadic templates
Java generics and C++ templates are completely different beasts. Java generics create a single type that stores a reference to Object and provides automatic casting in and out to the types in the interface, but the important bit is that it performs type erasure.
I would recommend that you explain the problem you want to solve and get suggestions for solutions to your problem that are idiomatic in C++. If you want to really mimic the behavior in Java (which, I cannot insist enough is a different language and has different idioms) you can use type erasure in C++ manually (i.e. use boost::any). But I have very rarely feel the need for full type erasure in a program... using a variant type (boost::variant) is a bit more common.
If your compiler has support for variadic templates (not all compilers do), you can always play with that, but stashing the fields for later in a vector may be a bit complicated for a fully generic approach unless you use type erasure. (Again, what is the problem to solve? There might be simpler solutions...)

Java generics are closer to just stuffing a boost::any into the self variable than to C++ templates. Give that a try. C++ templates create types that have no runtime or dynamic relarionship to each other by default.
You can introduce such a relationship manually, say via a common parent and type erasure and judicious use of pImpl and smart pointers.
C type variardic arguments are out of style in C++11. Variardic template arguments are very type safe, so long as your compiler has support for them (Nov 2012 CTP for MSVC 2012 has support for them (not update 1, the CTP), as does clang, and non-ancient versions of gcc).
Templates in C++ is a kind of metaprogramming, closer to writing a program that writes a program than it is to Java Generics. A Java Generic has one shared "binary" implementation, while each instance of a C++ template is a completely different "program" (which, via procedures like COMDAT folding, can be reduced to one binary implementation), whose details are described by the template code.
template<typename T>
struct Field {
T data;
};
is a little program that says "here is how to create Field types". When you pass in an int and double, the compiler does something roughly like this:
struct Field__int__ {
int data;
};
struct Field__double__ {
double data;
};
and you wouldn't expect these two types to be convertible between.
Java generics, on the other hand, create something like this:
struct Field {
boost::any __data__;
template<typename T>
T __get_data() {
__data__.get<T>();
}
template<typename T>
void __set_data(T& t) {
__data__.set(t);
}
property data; // reading uses __get_data(), writing uses __set_data()
};
where boost::any is a container that can hold an instance of any type, and access to the data field redirects through those accessors.
C++ provides means to write something equivalent to Java generics using template metaprogramming. To write something like C++ templates in Java, you'd have to have your Java program output custom Java byte or source code, then run that code in a way that allows a debugger to connect back to the code that writes the code as the source of the bugs.

There is no need to use wildcards in C++ templates, since in C++ it always knows the type, and is not "erased" like in Java. To write void foo(Field<?> bar, Field<?>... baz) method(or function) in C++, you would write:
template<class T, class... Ts>
void foo(Field<T> bar, Field<Ts>... baz);
Each Field<Ts> can be a different type. To use the variadic parameters inside the function, you just use baz.... So say you want to call another function:
template<class T, class... Ts>
void foo(Field<T> bar, Field<Ts>... baz)
{
foo2(baz...);
}
You can also expand the type with Field<Ts>..., so if you want to put it in a tuple(you can't put them in array since they can be different types):
template<class T, class... Ts>
void foo(Field<T> bar, Field<Ts>... baz)
{
std::tuple<Field<Ts>...> data(baz...);
}

This is not very idiomatic for C++. It can be done, perhaps; Coplien's book might have some ideas. But C++ is strongly typed because it believes in typing; trying to turn it into Smalltalk or fold it like a pheasant may lead to tears.

Related

How to know the required interface/contract of template arguments in C++?

Sorry for the newbie question, but I have a feeling I am missing something here:
If I have a certain class template which looks like this (basically the only way to pass a lambda to a function in C++, unless I am mistaken):
template<typename V, typename F>
class Something
{
public:
int some_method(V val, F func) {
double intermediate = val.do_something();
return func(intermediate);
}
}
By reading the implementation of this class, I can see that the V class must implement double do_something(), and that F must be a function/functor with the signature int F(double).
However, in languages like Java or C#, the constraints for the generic parameters are explicitly stated in the generic class signature, so they are obvious without having to look at the source code, e.g.
class Something<V> where V : IDoesSomething // interface with the DoSomething() method
{
// func delegate signature is explicit
public int SomeMethod(V val, Func<double, int> func)
{
double intermediate = val.DoSomething();
return func(intermediate);
}
}
My question is: how do I know how to implement more complex input arguments in practice? Can this somehow be documented using code only, when writing a library with template classes in C++, or is the only way to parse the code manually and look for parameter usage?
(or third possibility, add methods to the class until the compiler stops failing)
C# and Java Generics have similar syntax and some common uses with C++ templates, but they are very different beasts.
Here is a good overview.
In C++, by default template checking was done by instantiation of code, and requrements are in documentation.
Note that much of the requirements of C++ templates is semantic not syntactic; iterators need not only have the proper operations, those operations need to have the proper meaning.
You can check syntactic properties of types in C++ templates. Off the top of my head, there are 6 basic ways.
You can have a traits class requirement, like std::iterator_traits.
You can do SFINAE, an accidentally Turing-complete template metaprogramming technique.
You can use concepts and/or requires clauses if your compiler is modern enough.
You can generate static_asserts to check properties
You can use traits ADL functions, like begin.
You can just duck type, and use it as if it had the properties you want. If it quacks like a duck, it is a duck.
All of these have pluses and minuses.
The downside to all of them is that they can be harder to set up than "this parameter must inherit from the type Foo". Concepts can handle that, only a bit more verbose than Java.
Java style type erasure can be dominated using C++ templates. std::function is an example of a duck typed type eraser that allows unrelated types to be stored as values; doing something as restricted as Java is rarely worthwhile, as the machinery to do it is harder than making something more powerful.
C# reification cannot be fully duplicated by C++, because C#'s runtime environment ships with a compiler, and can effectively compile a new type when you instantiate at runtime. I have seen people ship compilers with C++ programs, compile dynamic libraries, then load and execute them, but that isn't something I'd advise.
Using modern c++20, you can:
template<Number N>
struct Polynomial;
where Number is a concept which checks N (a type) against its properties. This is a bit like the Java signature stuff on steroids.
And by c++23 you'll be able to use compile time reflection to do things that make templates look like preprocessor macros.

Equivalent to `<T extends MyClass>` in C++

In Java you can define a generic type, that should interhit from anoter, by <T extends MyClass> void myMethod(T item)
Is there an equivalent in cpp? I tried template<class T : Draw_Shape> class MyClass, but dont work.
When reading below, please be aware that I am not a Java programmer. My knowledge of Java is almost entirely abstract, and possibly out of date. So if Java implemented reification of generics in the last version or two I don't know about it.
So Java Generics and C++ templates share some common syntax and uses, but they are very different things under the hood.
Java Generics are a wrapper of automatically written casts and compile time type checks around a single core type.
C++ templates on the other hand generate new unrelated types for each set of template arguments.
The extends MyClass syntax in Java does two things. First, it permits that "core" type of the generic to know that the T is not merely an Object, but actually a subclass of some interface. This is required for the "core" type to use methods safely (without can-fail-at-runtime dynamic casts).
In C++ this doesn't happen because there is no "core" type generated by a template instantiation. Each template instantiation is independently compiled, and so knows if the operations are valid or not.
The second thing it does is it gives type errors when the wrong type is passed to the generic. The third thing it does is it allows Java to check the Generic code for validity prior to it being instantiated.
For the second, C++ can use concepts (if your compiler is new enough) or use a technique known as SFINAE that is equally powerful, but syntactically awful and honestly its ability to solve this problem was an accident of language development (it is accidentally Turing complete).
For the third, checked templates in C++, it has been proposed many times, but keeps running into compile time performance issues. So there isn't a way to do it in C++, short of instantiating a template.
Solutions:
Do nothing:
No, seriously. Embrace duck typing and don't constrain template parameters. The only big downside is ugly error messages, and rarely "same named operation has different meanings".
static_assert:
template<class T> class MyClass{
static_assert(std::is_base_of_v<Draw_Shape,T>);
};
this generates clean error messages. There are some downsides in that other code cannot test if MyClass<X> is a valid instantiation without a hard compiler error.
SFINAE:
template<class T,
std::enable_if_t<std::is_base_of_v<Draw_Shape,T>, bool> =true
>
class MyClass{
};
note that the =true does not compare the test to the value true. It is not ==true. What is going on here is ridiculously complex and annoying; using SFINAE for this purpose is a hack, and this is just a monkey-see monkey-do way to make it clean.
Concepts:
template<class T> requires std::is_base_of_v<Draw_Shape,T>
class MyClass{
};
or
template<std::is_derived_from<Draw_Shape> T>
class MyClass{
};
note that concepts requires a modern C++ complier and std library.

C++ Function templates for only types that extend the same superclass

I come from a C# background, where I would be able to do something like this
void AddComponent<T>() where T : Component, new()
{
T newT = new T();
//Do other things...
ListOfComponents.Add(newT);
}
I'm rather new when it comes to C++ Templates, but after visiting a number of tutorials and sites, I haven't been able understand how to replicate this.
Does anyone know if this is possible in C++ using templates?
If I understand correctly, the where is necessary in C# to tell the compiler that T can be created with new and can be added to the collection. Without that information, the function wouldn't compile.
In C++ you don't need to tell the compiler that information, just write the code you want to write, and if the type can be created with new and added to the collection, it will compile without problems. If it can't be created with new or can't be added to the collection, it won't compile. You don't need to tell the compiler anything about the type.
So just write something like:
template<typename T>
void AddComponent()
{
T newT = new T();
//Do other things...
ListOfComponents.insert(newT);
}
(Note that "creating with new" means something very different in C++, possibly what you really care about is whether it can be constructed with zero arguments).
The reason this works is that a C++ template is not just a function that operates on generic Object types and has some extra information telling it the objects can be cast to more specific types. A C++ template really is a "template" from which a concrete function is generated (kind of like C# reification, but different). If you instantiate a function template with int as the template parameter it generates a new function, which is distinct from the function generated by instantiating the template with float. So if you instantiate AddComponent<int>() the compiler generates a function equivalent to:
void AddComponent()
{
int newT = new int();
//Do other things...
ListOfComponents.insert(newT);
}
If that compiles then it compiles. You don't need to tell the compiler anything about int because it already knows whether you can use an int in that way. If you can't do those things with an int then it doesn't compile. C++ templates are much smarter than the limited "generics" in C# and Java, which are basically just operating on Object with some implicit casting inserted by the compiler, and so you need to provide constraints to tell the compiler what casting to do. (This is partly because C++ templates are not checked by the compiler until you instantiate them, so you can write a template that is full of errors, and only find out later when you try to use it by instantiating it. C# checks the definition of generics early to ensure they only use properties that are known to work because of the constraints).
Now, you can constrain a function template so it won't even try to compile if a template argument type doesn't meet certain requirements e.g.
template<typename T,
typename Requires = std::enable_if_t<std::is_base_of<Component, T>::value>>
void AddComponent()
{
T newT = new T();
//Do other things...
ListOfComponents.insert(newT);
}
This constraints the function template so it can only be called with types that have Component as a base class. You could also add a constraint using std::is_default_constructible<T>.
However this isn't necessary unless you want to overload AddComponent and have another function that does something different if the argument doesn't derive from Component (and/or isn't default constructible).
With the "Concepts" feature of C++, which is not yet part of the standard but is defined by an ISO Technical Specification and supported in GCC, you can do:
template<typename T>
void AddComponent() requires std::is_base_of<Component, T>::value
{
T newT = new T();
//Do other things...
ListOfComponents.insert(newT);
}
But again, this isn't necessary just to make the function compile, only if you want to have multiple overloads of AddComponent that do different things depending on the type they are instantiated with.
take a look at type_traits. You may narrow template application only to particular classes or class families using std::enable_if.

Bounded Type Parameters in C++, any reason for the lack of it?

Java and I guess C#(and others) support Bounded Type Parameters which lets us restrict what types may be used in template classes/functions.
I am curious if there is a reason, official or otherwise, for not adding native support for bounded types to C++? Anything to do with how templates are currently processed? Multiple inheritance issues?
I would expect it to be quite useful.
C++ has SFINAE which can be exploited via std::enable_if fairly easily. In conjunction with type_traits it is actually, IMO, more powerful than the bounded types that Java and C# have. With a little work you can also make some nice constexpr functions to test these things out for you. Combine that with some macros and you have something that looks sorta like it
#include <iostream>
#include <type_traits>
#define ENABLE_IF typename std::enable_if<
#define THEN(T) ,T>::type
class foo {};
class bar : public foo {};
template<class T, class U>
constexpr bool extends() {
return std::is_base_of<
typename std::remove_reference<U>::type,
typename std::remove_reference<T>::type
>::value;
}
template<class T>
ENABLE_IF extends<T, foo>() THEN(void) test(T&& v) {
std::cout << "T extends foo!!";
}
int main() {
test(bar{});
}
Now I'm not sure I would recommenced this but it is doable and as of now I see no issue in doing it beyond SFINAE being hard to debug
The simple fact is, the reason why this is not in is because nobody has come up with a feature that would make it work without horrific side effects. The Committee has been working on the problem for a decade or more, and the latest iteration still isn't fit for purpose.
Also, the generic restrictions you refer to are not bounded types at all. The only bound they support is "X inherits from Y", essentially, and frankly, SFINAE with std::is_base_of covers this situation just fine. C++ would need something far more powerful to be useful, since run-time inheritance is one of the least useful features.
Most of the time, the constraints on a template argument should not be on the type, but on the operations that the template needs. C++ does that, in a somewhat awkward way, simply because you get an error message if an operation that the template uses isn't there. For example:
template <class T>
void show(T t) {
std::cout << t << std::endl;
}
If you call this template function with a type that doesn't implement operator<< you'll get an error. The Java approach would be to define an interface with a print method, and require that the user pass an object of a type that implements that interface. The C++ approach doesn't require all that mechanism.
The problem with doing this in C++ is that you can get error messages that are very confusing. Often the missing operation is used in some low-level part of another template, and the error message has no clear relation to the code that you wrote. That's one of the drives behind concepts: the author of the template can set out what operations it uses, and passing an object whose type doesn't support those operations will result in a violation of the concept right at the interface, instead of deep within the implementation, so you will probably get a more useful error message.
The purpose of the bounded type parameter is to raise a compile-time error in case of a mismatch of the supplied type and a desired base-class, so this is easily achievable in C++11 and up, with a static_assert and supplying to it the value of the std::is_base_of as follows:
template <typename T>
class C {
static_assert(std::is_base_of<SomeBoundedBaseClass, T>::value, "Bounded type parameter violation!");
//...the rest of the class C
};
where SomeBoundedBaseClass is your class to which you want to bound the type parameter T to be a descendant of or match exactly.
Also note that this way you can mention any custom message to be shown as a compile error, so it has even an advantage over the Java's built-in functionality. Needless to say that C++ is more verbose, but it gives also more freedom.

typedef vs public inheritance in c++ meta-programming

Disclaimer: the question is completely different from Inheritance instead of typedef and I could not find any similar question so far
I like to play with c++ template meta-programming (at home mostly, I sometimes introduce it lightly at work but I don't want to the program to become only readable to anyone who did not bother learning about it), however I have been quite put out by the compiler errors whenever something goes wrong.
The problem is that of course c++ template meta-programming is based on template, and therefore anytime you get a compiler error within a deeply nested template structure, you've got to dig your way in a 10-lines error message. I have even taken the habit of copy/pasting the message in a text-editor and then indent the message to get some structure until I get an idea of what is actually happening, which adds some work to tracking the error itself.
As far as I know, the problem is mostly due to the compiler and how it output typedefs (there are other problems like the depth of nesting, but then it's not really the compiler fault). Cool features like variadic templates or type deduction (auto) are announced for the upcoming C++0x but I would really like to have better error messages to boot. It can prove painful to use template meta-programming, and I do wonder what this will become when more people actually get into them.
I have replaced some of the typedefs in my code, and use inheritance instead.
typedef partition<AnyType> MyArg;
struct MyArg2: partition<AnyType> {};
That's not much more characters to type, and this is not less readable in my opinion. In fact it might even be more readable, since it guarantees that the new type declared appears close to the left margin, instead of being at an undetermined offset to the right.
This however involves another problem. In order to make sure that I didn't do anything stupid, I often wrote my templates functions / classes like so:
template <class T> T& get(partition<T>&);
This way I was sure that it can only be invoked for a suitable object.
Especially when overloading operators such as operator+ you need some way to narrow down the scope of your operators, or run the risk of it been invoked for int's for example.
However, if this works with a typedef'ed type, since it is only an alias. It sure does not work with inheritance...
For functions, one can simply use the CRTP
template <class Derived, class T> partition;
template <class Derived, class T> T& get(partition<Derived,T>&);
This allows to know the 'real' type that was used to invoke the method before the compiler used the public inheritance. One should note that this decrease the chances this particular function has to be invoked since the compiler has to perform a transformation, but I never noticed any problem so far.
Another solution to this problem is adding a 'tag' property to my types, to distinguish them from one another, and then count on SFINAE.
struct partition_tag {};
template <class T> struct partition { typedef partition_tag tag; ... };
template <class T>
typename boost::enable_if<
boost::same_type<
typename T::tag,
partition_tag
>,
T&
>::type
get(T&)
{
...
}
It requires some more typing though, especially if one declares and defines the function / method at different places (and if I don't bother my interface is pretty soon jumbled). However when it comes to classes, since no transformation of types is performed, it does get more complicated:
template <class T>
class MyClass { /* stuff */ };
// Use of boost::enable_if
template <class T, class Enable = void>
class MyClass { /* empty */ };
template <class T>
class MyClass <
T,
boost::enable_if<
boost::same_type<
typename T::tag,
partition_tag
>
>
>
{
/* useful stuff here */
};
// OR use of the static assert
template <class T>
class MyClass
{
BOOST_STATIC_ASSERT((/*this comparison of tags...*/));
};
I tend to use more the 'static assert' that the 'enable_if', I think it is much more readable when I come back after some time.
Well, basically I have not made my mind yet and I am still experimenting between the different technics exposed here.
Do you use typedefs or inheritance ?
How do you restrict the scope of your methods / functions or otherwise control the type of the arguments provided to them (and for classes) ?
And of course, I'd like more that personal preferences if possible. If there is a sound reason to use a particular technic, I'd rather know about it!
EDIT:
I was browsing stackoverflow and just found this perl from Boost.MPL I had completely forgotten:
BOOST_MPL_ASSERT_MSG
The idea is that you give the macro 3 arguments:
The condition to check
a message (C++ identifier) that should be used for display in the error message
the list of types involved (as a tuple)
It may help considerably in both code self documentation and better error output.
What you are trying to do is to explicitly check whether types passed as template arguments provide the concepts necessary. Short of the concept feature, which was thrown out of C++0X (and thus being one of the main culprits for it becoming C++1X) it's certainly hard to do proper concept checking. Since the 90ies there have been several attempts to create concept-checking libraries without language support, but, basically, all these have achieved is to show that, in order to do it right, concepts need to become a feature of the core language, rather than a library-only feature.
I don't find your ideas of deriving instead of typedef and using enable_if very appealing. As you have said yourself, it often obscures the actual code only for the sake of better compiler error messages.
I find the static assert a lot better. It doesn't require changing the actual code, we all are used to having assertion checks in algorithms and learned to mentally skip over them if we want to understand the actual algorithms, it might produce better error messages, and it will carry over to C++1X better, which is going to have a static_assert (completely with class designer-provided error messages) built in into the language. (I suspect BOOST_STATIC_ASSERT to simply use the built-in static_assert if that's available.)