Can I rely on template type? - c++

I am looking into working code from Game AI by example book and there is a part I do not understand.
There is
template <class node_type, class edge_type>
class SparseGraph
{ ... };
and
int SparseGraph<node_type, edge_type>::AddNode(node_type node)
{
if (node.Index() < (int)m_Nodes.size())
...
}
How can be node.Index()called?
There also is class
class GraphNode
{
public:
...
int Index()const{return m_iIndex;}
....
};
and graph is created with this class
typedef SparseGraph<GraphNode, GraphEdge> NavGraph;
NavGraph * m_pGraph;
so I understand what node.Index() does, BUT
how can I call node.Index() while there is no guarantee that node_type is GraphNode.
what if node_type is not GraphNode??
Hope you understand my question.

If node_type is not GraphNode, then your compiler will smack you and throw an error. However, if your class depends on the Index function, then you should document it as a requirement and any replacement for GraphNode must provide it, probably with some expected semantics.

Duck typing.
There is also a convenient feature in C++ called SFINAE (Substitution Failure Is Not An Error) that will remove a template from the considered candidates if an expression dependent on the type would not compile with the particular concrete type.
A way of restricting the types accepted as template parameters based on supported operations, i.e. Concepts, was originally planned for C++0x but scrapped due to committee disagreement on its design. You can still find early implementations in some forks of GCC and Boost also has a concepts library. See here.

C++ template functions are instantiated at point of use. i.e., it will paste in the types you specify when you specify them, and not sooner. At that point, if the type you specify does not have an Index member function, the compilation will fail.

Related

C++ partial concept id: What is the reason for the explicit template specification order / special status of first argument?

I started experimenting with the C++20 feature of concepts and was very pleased when I realized that it is possible to partially explicitly provide template arguments for concepts. I read the cppreference article and did not find that mentioned there.
But then I realized something strange: the order of specification of template arguments is reversed to what I would have expected. When providing one explicite template argument, it replaces the second template in the template list:
#include <concepts>
#include <type_traits>
/// Concept in order to deduce if sth. is base of sth else
template <typename Impl, typename Base> //XXX: here the order of Impl and Base are not
concept Implements = std::is_base_of_v<std::remove_reference_t<Base>, // what I would've expected.
std::remove_reference_t<Impl>>;
/// Example Base class impl
struct BaseExample {};
/// Implementation of BaseExample
struct ImplExample : BaseExample {};
/// Function in which the concept is applied
template <Implements<BaseExample>... Baes> void f(Baes &&... ) {}//} ((void)b, ...); }
int main() {
(void) std::is_base_of_v<BaseExample, std::remove_reference_t<ImplExample &&>>; //< true
(void) std::is_base_of_v<BaseExample, std::remove_reference_t<ImplExample&>>; //< true
f(ImplExample{}, ImplExample{});
}
From my point of view the possibility to partially provide explicit template arguments makes sense, as the argument against partial template specification for classes do not apply here and make concepts more general. Now I wonder:
Will partial explicit template specifications (likely) be allowed when the standard is released?
Will this order of specifications likely stay the same or is this a bug?
How would I answer this question for myself? From what I understand the c++20 standard is not ready by now and I found a list of C++ Standard Committee Papers, of which I briefly searched the headlines of the ones proposed in 2020 for 'concept'. Is checking these papers the way to go, or is there an accessible single document which combines the points the authors currently agreed upon?
The code can be found here.
edit
After posting this I checked the behavior when three template arguments are specified. It looks like I misinterpreted the specification order: The first argument is 'held free' to contain the argument to be checked, and the explicit specifications start with the second argument. This can be seen here.
Even though I figured out the reasoning behind the order of specification I would be very interested in the answers to questions above.
Yes, partial-concept-ids are surely a C++20 thing. The special status of the first argument, while surprising, allows cases like std::constructible_from which is declared as
template<class T,class ...Args>
concept constructible_from=…;
std::constructible_from<int,int> is a type-constraint that requires that whatever it introduces be constructible from two int arguments. However, it can also be an expression, in which case it reports whether an int can be constructed from an int (spoilers: true), but that potential confusion exists regardless of the argument order.
If T had to go at the end, there would be no way of using such a concept: only template argument deduction or default template arguments can supply values for a template parameter beyond a parameter pack, and neither of those applies here.
Every mailing posted at the papers site you linked includes the latest draft of the standard, and alternate mailings include annotations as to what papers were adopted. Or you can just visit the draft’s repository (at least if you’re happy reading LaTeX).

How can I get Eclipse to make assumptions about my template parameters?

I have
template <typename T> class Foo : public T { /* ... */ }
and I only instantiate it with Ts which are subclasses of Bar. If it helps, I can static_assert that's the case.
So, Eclipse CDT doesn't recognize T is "really" also a Bar. I can't complain about that - but can I make it understand that? That is, can I somehow tell the Indexer to look for methods and types in class Bar as a base class of Foo?
This is a really good question!
Currently, there is no way to tell Eclipse that a template will only be instantiated with arguments that are subclasses of a particular type.
However, there is an upcoming C++ language feature that will allow you to express this relationship in your code, and for Eclipse to pick up on it as well: Concepts.
Concepts allow you to constrain template parameters such that they have to satisfy a concept, which can be thought of as a type predicate - a boolean function on types, evaluated at compile-time.
For example, you can write a concept like this:
template <typename T>
concept bool DerivedFromBar = std::is_base_of<Bar, T>::value;
This defines a concept DerivedFromBar which is satisfied only by types that are derived from Bar.
You can then use this concept in your class template definition:
template <DerivedFromBar T> class Foo : public T { /* ... */ }
Note the use of DerivedFromBar instead of the usual typename to declare the template parameter T. This tells the compiler that T is constrained to satisfy DerivedFromBar.
Once you express your code in this way, Eclipse can, in principle, make inferences that would allow it to offer members of Bar as auto-completion proposals when calling a method on an object of type T inside the template.
Concepts is currently supported by GCC, with other compilers such as MSVC and clang working on implementing it.
Bug 492682 tracks Concepts support in Eclipse CDT. Taking advantage of Concepts for better auto-completion would then be a follow-up feature.

Static polymorphism: How to define the interface?

Below is a very simple example of what I understand as static polymorphism. The reason why I'm not using dynamic polymorphism is that I do not want to obstruct inlining of functions of PROCESSOR in op.
template <class PROCESSOR>
void op(PROCESSOR* proc){
proc->doSomething(5);
proc->doSomethingElse();
}
int main() {
ProcessorY py;
op<ProcessorY>(&py);
return 0;
}
The problem with this example is: There exists no explicit definition of what functions a PROCESSOR has to define. If one is missing, you will just get a compile error. I think this is bad style.
It also has a very practical drawback: On-line assistance of IDEs cannot of course show you the functions that are available on that object.
What is a good/official way to define the public interface of a PROCESSOR?
There exists no explicit definition of what methods a PROCESSOR has to define. If one is missing, you will just get a compile error. I think, this is bad style.
It is. It is not. It may be. It depends.
Yes, if you want to define behavior in this way, you may want to also restrict the content, that template parameters should have. Unfortunately, it is not possible to do this "explicitly" right now.
What you want is constraints and concepts feature, that was supposed to appear as part of C++ 11, but was delayed and is still not available as of C++ 14.
However, getting compile-time error is often the best way to restrict template parameters. As an example, we can use std library:
1) Iterators.
C++ library defines few types of iterators: forward_iterator, random_access_iterator and others. For each type, there is a set of properties and valid expressions defined, that are guaranteed to be available. If you used iterator, that is not fully compatible with random_access_iterator in container, that requires random_access_iterator, you will get compiler error at some point (most likely, when using dereference operator ([]), which is required in this iterator class).
2) Allocators.
All containers in std library use allocator to perform memory allocation/deallocation and objects construction. By default, std::allocator is used. If you want to exchange it with your own, you need to ensure, that it has everything, that std::allocator is guaranteed to have. Otherwise, you will get compile-time error.
So, until we get concepts, this is the best and most widely used solution.
First, I think there is no problem with your static polymorphism example. Since it's static, i.e. compile-time resolved, by definition it has less strict demands regarding its interface definition.
Also it's absolutely legitimate that the incorrect code just won't compile/link, though a more clear error message from the compiler would be nicer.
If you, however, insist on interface definition, you may rewrite your example the following way:
template <class Type>
class Processor
{
public:
void doSomething(int);
void doSomethingElse();
};
template <class Type>
void op(Processor<Type>* proc){
proc->doSomething(5);
proc->doSomethingElse();
}
// specialization
template <>
class Processor<Type_Y>
{
// implement the specialized methods
};
typedef Processor<Type_Y> ProcessorY;
int main() {
ProcessorY py;
op(&py);
return 0;
}

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.)