While reading Wikipedia's page on decltype, I was curious about the statement,
Its [decltype's] primary intended use is in generic
programming, where it is often
difficult, or even impossible, to name
types that depend on template
parameters.
While I can understand the difficulty part of that statement, what is an example where there is a need to name a type that cannot be named under C++03?
EDIT: My point is that since everything in C++ has a declaration of types. Why would there ever be a case where it is impossible to name a type? Furthermore, aren't trait classes designed to yield type informations? Could trait classes be an alternative to decltype?
The wikipedia page you link has a perfect example:
int& foo(int& i);
float foo(float& f);
template <class T> auto transparent_forwarder(T& t) −> decltype(foo(t)) {
return foo(t);
}
Note that foo(int&) returns int& (a reference type) while foo(float&) returns float (a nonreference type). Without decltype, it's impossible within the template to specify a type which represents "the return type of the function foo which takes an argument t of type T".
In this example, it's not a particular concrete type which is impossible to express -- either int& or float are individually expressible -- but a higher level generic class of types.
EDIT: and to answer your comment to another answer, this example is inexpressible in C++03. You cannot have a function template which will wrap any function T1 foo(T2) and match both argument and return type of the wrapped function.
There are types in C++0x (and in C++03, but less often) that cannot be named explicitly, such as the type decltype(f) after the declaration auto f = [](int x) -> int {return x;};. You would need to typedef that decltype result to something to get a name at all. Traits classes can be used for determining return types, but they are messy, and the user needs to duplicate all of their function overloads with traits class overloads; that is difficult to do correctly for cases such as functions applying (through implicit conversion of pointers) to all subclasses of a given base class.
As you pointed out, the type if it exist is known by the compiler, otherwise it wouldn't exist. However, it is not always readily or even accessible to the programmer in C++03.
N1607 mention the following in its conclusion:
In C++2003, it is not possible to
express the return type of a function
template in all cases. Furthermore,
expressions involving calls to
function templates commonly have very
complicated types, which are
practically impossible to write by
hand
The question is how do we access this type as a programmer. This is not always a trivial process, often impracticable. It is increasingly complex when you have an expression for which you desire to know the result type. You would have to break it into pieces in order to figure the result types. It is not possible to simplify this process using templates (not without evaluating the expression anyhow). Breaking the expression will be error-prone, tedious and a nightmare to maintain. Think of this code:
x.g()[b.a(e)]->f();
With C++98/TR1, it is often infeasible to name types that depend on template parameters. Traits offers us so much information, but eventually decltype is a much cleaner solution to many problems. A lot of the information available to you when meta programming is only available because libraries, such as boost or loki, use several tricks hidden in the dark corners of the C++98 language.
Of course this is irrelevant to your question but I believe that it is worthy to mention that C++98 compilers already have mechanics to know these types. This is exactly what sizeof offers, except that it returns you a size. decltype reuse some of this functionality and solves these problems with greater elegance.
As for a different (academic) example:
struct Foo
{
struct
{
int x;
} bar;
};
template<typename T>
void
f(const T& t)
{
// C++03, How can I name the type of T::bar ?
// C++0x
// decltype(t.bar) cpy;
// Do stuff with our local cpy
}
int
main()
{
f(Foo());
}
Related
Auto keyword is used to infer the type of the variable based on the initialization. But I read on internet that auto can't determine the type of the function parameters. I didn't understand the reason why auto can't determine the type when used with function parameters. Can any one please let me know why auto can't be used with function parameters and any other cases where auto keyword can't be used to determine the type.
"Can't" is a strong word. After all, lambda parameters can use auto (in C++14). It's not so much "can't" as "doesn't". And perhaps "won't".
The question ultimately comes down to this: what does this actually do?
void foo(auto x)
{
std::cout << x << std::endl;
}
auto deduction is ultimately based on providing an initializing expression, which is used to deduce the actual type. This declaration contains no initializing expression.
C++ is a statically typed language; that means the compiler must be able to determine the type of every expression and object at compile time. From just the above, the compiler can deduce nothing.
So how can the compiler know that std::cout << x is legal C++ syntax? It can only tell that if there is an operator<< overload that takes std::cout and x. It can't figure out what is being called without first knowing the type of x. Which it doesn't; it can be different for different invocations of the function.
However, there is one C++ construct where the above makes sense: a template. This is exactly what using auto in lambda parameters does; it implicitly transforms the function into a template function. So [](auto x) {return x;} effectively becomes an operator something like this:
template<typename T>
auto operator()(T x) {return x;}
However, this conversion doesn't just fall out of having auto as a deduction syntax. It has to be something the standard is explicitly written to require. And, with the exception of C++14 generic lambdas, it doesn't.
Concepts TS includes this facility. However, this is merely an extension of the ability to use concepts in function parameter lists at all. That is, they already have a way to make a function implicitly create a template function, so they just added auto as essentially a case of "a concept that accepts any type".
But this was explicitly excluded from the C++20 version of concepts. The general reason for this exclusion is that, up until this point, template functions could be detected because they always had to have some special syntax. Namely, the inducer template<args>. With the Concepts TS version, there is concern that people will write template functions without realizing it.
And template functions behave differently from non-template functions. A template function is a family of functions, so you can't get a pointer to the family itself. You'd have to explicitly instantiate the template to get a pointer to that particular function.
I have been looking into type_traits recently & was wondering why are they implemented as class templates whereas implementing them as functions could be more obvious & have a simpler syntax.
What I want to say is this syntax :-
int x = 5;
std::cout << is_same<int>(x);
Is more convincing & cleaner than the actual one ie :-
int x = 5;
std::cout << is_same <int, decltype(x)>::value;
This is just a case of curiosity. I just want to know the philosophy of the Standardization Committee in preferring the class method over the function method.
Versality. Most type traits have both X::value boolean constant and X::type type alias which can be used for tag dispatch.
Ability to partially specialize. You cannot have partial specialization for function, only full specializations and overloads. It is easy to call wrong function in presence of both specializations and overloads.
Compile-time evaluation. Most of type traits were invented in previous millenia, when constexpr functions were not avaliable. Even in constexpr functions you cannot pass values as parameter, as it might prevent compile-time evaluation.
You always have type, but sometimes it is all you have. Creating a function which does not work all the time is counterproductive, so we will not be able to rely on template parameter deduction anyway.
C++14 will allow the creation of variables that are templated. The usual example is a variable 'pi' that can be read to get the value of the mathematical constant π for various types (3 for int; the closest value possible with float, etc.)
Besides that we can have this feature just by wrapping a variable within a templated struct or class, how does this mix with type conversions? I see some overlapping.
And other than the pi example, how would it work with non-const variables? Are there any usage examples to understand how to make the most of such a feature and what its purpose is?
And other than the pi example, how would it work with non-const
variables?
Currently, it seems to instantiate the variables separately for the type. i.e., you could assign 10 to n<int> and it would be different from the template definition.
template<typename T>
T n = T(5);
int main()
{
n<int> = 10;
std::cout << n<int> << " "; // 10
std::cout << n<double> << " "; // 5
}
If the declaration is const, it is readonly. If it's a constexpr, like all constexpr declarations, it has not much use outside constexpr(ressions).
Besides that we can have this feature just by wrapping a variable
within a templated struct or class, how does this mix with type
conversions?
It's meant to be a simple proposal. I am unable to see how it affects type conversions in a significant way. As I already stated, the type of the variable is the type you instantiated the template with. i.e., decltype(n<int>) is int. decltype((double)n<int>) is double and so on.
Any usage example to understand how to make the most of such a feature
and what its purpose is?
N3651 provides a succinct rationale.
Alas, existing C++ rules do not allow a template declaration to
declare a variable. There are well known workarounds for this
problem:
• use constexpr static data members of class templates
• use constexpr function templates returning the desired values
These workarounds have been known for decades and well documented.
Standard classes such as std::numeric_limits are archetypical
examples. Although these workarounds aren’t perfect, their drawbacks
were tolerable to some degree because in the C++03 era only simple,
builtin types constants enjoyed unfettered direct and efficient
compile time support. All of that changed with the adoption of
constexpr variables in C++11, which extended the direct and efficient
support to constants of user-defined types. Now, programmers are
making constants (of class types) more and more apparent in programs.
So grow the confusion and frustrations associated with the
workarounds.
...
The main problems with "static data member" are:
• they require "duplicate" declarations: once inside the class
template, once outside the class template to provide the "real"
definition in case the con- stants is odr-used.
• programmers are both miffed and confused by the necessity of providing twice the same
declaration. By contrast, "ordinary" constant declarations do not need
duplicate declarations.
...
Well known examples in this category are probably static member
functions of numeric_limits, or functions such as
boost::constants::pi<T>(), etc. Constexpr functions templates do not
suffer the "duplicate declarations" issue that static data members
have; furthermore, they provide functional abstraction. However, they
force the programmer to chose in advance, at the definition site, how
the constants are to be delivered: either by a const reference, or by
plain non- reference type. If delivered by const reference then the
constants must be systematically be allocated in static storage; if
by non-reference type, then the constants need copying. Copying isn’t
an issue for builtin types, but it is a showstopper for user-defined
types with value semantics that aren’t just wrappers around tiny
builtin types (e.g. matrix, or integer, or bigfloat, etc.) By
contrast, "ordinary" const(expr) variables do not suffer from this
problem. A simple definition is provided, and the decision of
whether the constants actually needs to be layout out in storage only
depends on the usage, not the definition.
we can have this feature just by wrapping a variable within a templated struct or class
Yes, but that would be gratuitous syntactic salt. Not healthy for the blood pressure.
pi<double> conveys the intent better than pi<double>::value. Short and to the point. That's enough of a reason in my book to allow and encourage this syntax.
Another practical example for C++14's variable templates is when you need a function for passing something into std::accumulate:
template<typename T>
T const & (*maxer) (T const &, T const &) = std::max<T>;
std::accumulate(some.begin(), some.end(), initial, maxer<float>);
Note that using std::max<T> is insufficient because it can't deduce the exact signature. In this particular example you can use max_element instead, but the point is that there is a whole class of functions that share this behavior.
I wonder whether something along these lines would be possible: (assuming availability of template lambdas)
void some_func() {
template<typename T>
std::map<int, T> storage;
auto store = []<typename T>(int key, const T& value) { storage<T>[key] = value; };
store(0, 2);
store(1, "Hello"s);
store(2, 0.7);
// All three values are stored in a different map, according to their type.
}
Now, is this useful?
As a simpler use, notice that the initialization of pi<T> uses explicit conversion (explicit call of a unary constructor) and not uniform initialization. Which means that, given a type radians with a constructor radians(double), you can write pi<radians>.
Well, you can use this to write compile time code like this:
#include <iostream>
template <int N> const int ctSquare = N*N;
int main() {
std::cout << ctSquare<7> << std::endl;
}
This is a significant improvement over the equivalent
#include <iostream>
template <int N> struct ctSquare {
static const int value = N*N;
};
int main() {
std::cout << ctSquare<7>::value << std::endl;
}
that people used to write to perform template metaprogramming before variable templates were introduced. For non-type values, we were able to do this since C++11 with constexpr, so template variables have only the advantage of allowing computations based on types to the variable templates.
TL;DR: They don't allow us to do anything we couldn't do before, but they make template metaprogramming less of a PITA.
I have a use case here.
template<typename CT> constexpr CT MARK = '%';
template<> constexpr wchar_t MARK<wchar_t> = L'%';
which are used in a string processing template.`
template <typename CT>
void ProcessString(const std::basic_string<CT>& str)
{
auto&& markpos = str.find(MARK<CT>);
...
}
So I understand using var in C# makes sense because you have anonymous types that are compiler derived. C++ doesn't seem to have this feature (unless I'm wrong), so what is the point of having an auto keyword?
(It is kinda cool that unlike C#, auto does work for member/global variables, which is cool I guess, but doesn't seem enough to justify its existence).
auto has a lot of uses when it comes down to both generic programming and to save the programmer some typing.
For example, consider this. Would you rather type out:
std::unique_ptr<name::long_type::goes_here> g =
std::make_unique<name::long_type::goes_here>(1,2,3,4)
or:
auto g = std::make_unique<name::long_type::goes_here>(1,2,3,4)
Yes, they're both long but we know the return type and specifying it again is a bit cumbersome to type. This also goes for iterators:
for(auto i = vec.begin(); ...)
vs:
for(std::vector<type>::iterator i = vev.begin(); ...)
Its use in generic programming is also to figure out the return type of a function or if you're doing some generic algorithms where you don't know the type.
For example, consider a very basic example.
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
This allows the compiler to figure out the type of the add operation rather than us trying to figure it out ourselves. Note that in C++14 you can omit the trailing return type. Its uses in generic programming don't stop there either. If we wanted to work with any type of container as a wrapper function for algorithms we could use auto to help us with it. For example:
template<class Cont>
void my_sort(Cont&& cont) {
using std::begin;
auto first = begin(std::forward<Cont>(cont));
// work with the iterators here
}
In the future (C++14), auto can be used to make polymorphic lambdas as well such as:
[](auto a) { return a + 4; }
Which can be useful as well.
There are a number of uses for auto in C++
Anonymous function objects, aka closures, aka lambda instances. auto is the only way to store them. Types can also be generated derived off those types, and types on their backs, ad infinitum.
C++ can have quite complex types, such as the type of a non mutating iterator into an unordered map that uses a custom allocator and hashing function. typedef can mitigate this, but the type of a m.begin() having a particular name is not that informative: foo_iterator it = is as meaningful as auto foo_iterator =, and the auto one does not require boilerplate elsewhere.
Return type deduction uses the auto keyword, which is required to do some template functions work without huge amounts of traits boilerplate. Eliminating boilerplate is a common theme: C++s robust type system means that types can carry lots of information, and encoding it at every use can be counterproductive.
In some ducktype template code, the work to deduce the type of a variable is roughly the same as the work to code the variables value, and nearly identical in structure, some times literally: decltype(long expression) x = long expression;. auto eliminates that duplication.
Finally in C++1y, type deduction lambdas use auto to say that an argument is a deduced one. Sort of a light weight template. Talk to extend this to non lambdas is also in skunkworks.
HEre's a real life example where I could not, not use auto
I was trying to do a switch type statement in C++ where the return type is implementation specific and could not be declared easily. So using an 'auto' is probably the right way to resolve the type look up for the map declaration.
auto foo = boost::bind(&VegaFactory::load_commodity_one_leg,this,conn,_1);
std::map<std::string,decltype(foo)> methods;
methods.insert(std::make_pair("FOO",commodityOneLeg));
auto f = methods.find(bar);
// Call f here
C++ does have "anonymous" types - types you cannot refer to by name because the name is not available to you. This was the case even before C++11 and lambdas. Consider the following code:
class foo {
class bar {
public:
void baz() { }
};
public:
static bar func() { return bar(); }
};
foo::func().baz(); // OK, only the name "bar" is private
??? a = foo::func(); // Umm...
auto b = foo::func(); b.baz(); // Hooray!
Even if not actually declared in a private scope, it is often useful for a library to leave some types unspecified in its API - especially when heavily utilizing expression templates or other template metaprogramming where the type names can be arbitrarily long with all the nested template arguments. Even the standard itself does this - for instance, the result type of std::bind is not defined by the specification.
syntactic sugar
I rather say
auto i = mapping.begin();
over
std::map<int, int>::iterator i = mapping.begin();
It is well worth reading Herb Sutter's article Almost Always Auto for some great examples of why it's worth using auto over explicit types. The main advantages are the reduction in typing, and gives additional safety if the underlying types change. One of my favourite examples though is about how it reduces duplication. If you allocate on the stack then you'd use:
MyClass c(param);
However, if you want to create on the heap you need:
MyClass* c=new MyClass(param);
So you've had to duplicate the MyClass, but the RHS already forces the variable to be a MyClass pointer, so you can just use this instead:
auto c=new MyClass(param);
If you want to declare it as a unique_ptr then previously you would need:
unique_ptr<MyClass> c=make_unique<MyClass>(param);
which can be abbreviated to:
auto c=make_unique<MyClass>(param);
In C++, auto keyword provides a way of type deduction mechanism. For example,
auto i = expressions;
auto keyword tells the compiler to determine the type of variable i from the expression on the right side of the assignment operator.
Therefore if the value of expressions is double, then variable i will be double. Or, if the value of expressions is bool, then variable i will be bool.
so, let's learn type inference first which is basically refers to automatic deduction of the data type of an expression in a programming language.
before C++ 11 all the variables in c++ have to explicitly declare but after the release of c++ 11, the compiler itself deduces the type of the variable at runtime.
we can use it for variables and even in the case of function return types.
but, it's suggested to avoid using auto in function return type.
Concepts didn't make the C++0x standard, but Boost still provides The Boost Concept Check Library (BCCL). I guess that BCCL doesn't cover everything that was meant to into the C++0x standard. What is the difference between BCCL and the proposed C++0x solution?
Checking the template definition
A big difference of concepts to these manual solutions is that concepts allow the definition of a template to be type-checked without doing anything special. The concept check library allows only the *use* of it to be type checked (unless you manually write test-instantiation types or make use of provided types for standard cases, see below). Example:
template<typename InputIterator>
int distance(InputIterator a, InputIterator b)
{ return b - a; }
You may now sprinkle that template with concept checks and traits, but you will never get an error after writing that template - because the Standard allows the compiler to delay compiling the template until instantiation. For checking, you have to write "archetype" classes, which contain exactly those operations that are required by the interface and then instantiate them artificially.
Reading the documentation of BCCL, i found it already includes the common archetypes like "default constructible". But if you write your own concepts, you will have to also provide your own archetypes, which isn't easy (you have to find exactly the minimal functionality a type has to provide). For example, if your archetype contains a operator-, then the test of your template with that (incorrect) archetype will succeed, although the concepts don't require such an operator.
The rejected concepts proposal creates archetypes for you automatically, based on the requirements that were specified and that were implied (a pointer type T* used in a parameter will imply the PointeeType requirement for T, for example). You don't have to care about this stuff - except of course when your template definition contains a type error.
Checking semantic requirements
Consider this code, using hypothetical concept checks
template<ForwardIterator I>
void f(I a, I b) {
// loop two times!
loopOverAToB(a, b);
loopOverAToB(a, b);
}
The BCCL manual says that semantic requirements are not checked. Only syntax requirement and types are checked. Consider a forward iterator: There exists the semantic requirement that you may use it in multi-pass algorithms. Syntax-checking only won't be able to test this requirement (think about what happens if a stream iterator accidentally would pass that check!)
In the rejected proposal, you had to explicitly put auto in front of concept definitions to make the compiler flag success after syntax-checking. If auto wasn't specified, then a type explicitly had to define a concept map to say it supports that concept. A stream iterator would thus never be taken to pass a ForwardIterator check.
Syntax remapping
This was another feature. A template such as
template<InputIterator I>
requires OutputStreamable<I::value_type>
void f(I a, I b) {
while(a != b) std::cout << *a++ << " ";
}
Can be used like the following, if the user would provide a concept map that teaches the compiler how to dereference an integer, and thus how an integer satisfies the InputIterator concept.
f(1, 10);
This is the benefit of a language-based solution, and cannot be solved by BCCL ever, i believe.
Concept based Overloading
On a quick read of BCCL, i can also not spot anything that allows this to happen. A concept matching failure seems to cause a hard compilation error. The rejected proposal allows the following:
template<ForwardIterator I>
I::difference_type distance(I a, I b) {
I::difference_type d = 0; while(a != b) ++a, ++d;
return d;
}
template<RandomAccessIterator I>
I::difference_type distance(I a, I b) {
return b - a;
}
If a type could be used with both templates, then the second template would be used, because it's more specialized: RandomAccessIterator refines the ForwardIterator concept.
The C++0x concept feature would be a core language feature, whose whole process would be done by the compiler.
The Boost Concept Check Library is the almost same feature but written in C++ and macro as a library to simulate some of the feature. It cannot do all that would be required in the final language feature (depending on the final feature definition) but provide some equivalent solutions for template type checking (and other compile time checks).
As suggested, as the C++0x concept is a language features, it would allow to provide more elegant semantic and allow compiler to use informations not currently available to the program, allowing more detailed or intelligent errors at compile time (as the concept first purpose is to allow abstract type check in templates).
Disclaimer: I wasn't able to successfully use BCCL within the last 30 minutes even though I had Boost installed already. The example you see below looks OK according to the BCCL documentation of Boost 1.37 but didn't work. I guess this counts as disadvantage.
With BCCL you only get something like static assertions whereas the core language concept feature provides full modular type checking and is able to prevent some function template from participating in overload resolution. With native concepts the body of a constrained template can be checked immediately by the compiler whereas BCCL doesn't make the compiler check anything in that respect. You have to manually instantiate your template with "arche type" parameters to see if the template uses any operations that are not available (for example, operator-- on forward iterators).
As for overload resolution here's an example:
template<typename Iter>
void foo(Iter,Iter) {
BOOST_CONCEPT_ASSERT((RandomAccessIterator<Iter>));
}
void foo(long, int);
int main() {
foo(2,3); // compile-time error
}
The template is a better match because the non-template requires a conversion from int to long. But instantiation fails because int is not an iterator. You get a nice error message explaining it but that's not very satisfying, is it? With native concepts you could have written
template<typename Iter>
requires RandomAccessIterator<Iter>
void foo(Iter,Iter) {}
void foo(long, int);
int main() {
foo(2,3); // OK, picks non-template foo
}
Here, the function template will not take part in overload resolution because the requirement for T=int is not satisfied. Great!
We still get to constrain function templates with the SFINAE trick. C++0x extends SFINAE to expressions and together with decltype and default template arguments for function templates we can write
template<typename T> T&& make();
template<typename Iter, class = decltype( *make<Iter>() )>
void foo(Iter,Iter) {}
void foo(long, int);
int main() {
foo(2,3); // OK, picks non-template foo
}
In this case, template argument deduction will fail silently because the compiler doesn't know what the type of the expression ∗make<Iter>() is supposed to be (we can't dereference an int). With a bit of template metaprogramming and some macros we can get pretty close to imposing arbitrary structural constraints on template parameters in a readable way. Here's what it might look like assuming appropriate definitions for REQUIRES and RandomAccessIterator:
template <typename Iter
REQUIRES( RandomAccessIterator<Iter> )
>
void foo(Iter,Iter) {}
HTH,
S