I actually really like the automatic type deduction in C++, where I can have an arbitrarily complex return type from a function, but not worry about what the type is when calling the function.
In other words, something like:
std::vector<std::map<std::string, std::string>> getCollection() { ... }
auto myMapArray = getCollection();
However, this appears to work only if the compiler can deduce the type, such as when it's initialised from the function.
I often find myself in a situation where I just want a default-constructed variable of the correct type (usually a class member variable) and it pains me to have to do:
std::vector<std::map<std::string, std::string>> getCollection();
std::vector<std::map<std::string, std::string>> m_collection;
in this case. But I know of no other way to avoid the long type names, other than using typedef
or the more modern using
:
typedef std::vector<std::map<std::string, std::string>> VecOfMaps;
using VecOfMaps = std::vector<std::map<std::string, std::string>>;
:
VecOfMaps m_collection;
It appears it would be useful to allow type deduction of a variable as if it were something returned from a function, such as with:
std::vector<std::map<std::string, std::string>> getCollection() { ... }
auto m_collection = asif(getCollection);
You wouldn't need to provide parameters since all overloads are required to return the same type. So my questions are really:
asif
solution (it would have to allow for templated functions but that should just be a minor extension)?Concerning your comment:
It appears it would be useful to allow type deduction of a variable as if it were something returned from a function, such as with:
std::vector<std::map<std::string, std::string>> getCollection() { ... } auto m_collection = asif(getCollection);
It appears to me that asif()
sounds somehow like decltype().
In this case, it is the return type of function which is required, hence it should be
decltype(getCollection()) m_collection;
I must admit that I'm not that experienced with the practical use of decltype()
in daily business and fiddled myself a bit (out of curiosity), ending up with:
#include <iostream>
#include <map>
#include <string>
#include <vector>
auto func() { return std::vector<std::map<std::string, std::string>>(); }
struct Class {
typedef decltype(func()) VarType;
VarType var;
};
int main()
{
Class obj;
std::cout << "type of Class::var: " << typeid(obj.var).name() << '\n';
}
The output of that is:
type of Class::var: St6vectorISt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_St4lessIS6_ESaISt4pairIKS6_S6_EEESaISD_EE
So far, so good.
Can I do a
decltype(fn()) variable;
without a type alias?
#include <iostream>
#include <map>
#include <string>
#include <vector>
auto func() { return std::vector<std::map<std::string, std::string>>(); }
struct Class {
decltype(func()) var;
};
int main()
{
Class obj;
std::cout << "type of Class::var: " << typeid(obj.var).name() << '\n';
}
Output:
type of Class::var: St6vectorISt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_St4lessIS6_ESaISt4pairIKS6_S6_EEESaISD_EE
I must admit that it was one of the samples in the linked decltype() documentation which made me sure about this.
Furthermore, I would like to mention that decltype()
is (similar like e.g. sizeof
) a compile-time type-only evaluation. Hence, it even works if there is no implementation of func()
available at all:
#include <iostream>
#include <map>
#include <string>
#include <vector>
std::vector<std::map<std::string, std::string>> func();
struct Class {
decltype(func()) var;
};
int main()
{
Class obj;
std::cout << "type of Class::var: " << typeid(obj.var).name() << '\n';
}
Output:
type of Class::var: St6vectorISt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_St4lessIS6_ESaISt4pairIKS6_S6_EEESaISD_EE
It looks like I can do the former but I want to make sure it's a standard thing and not just a gcc extension.
As far as I know, decltype()
is in fact a C++ standard feature (since C++11 and the fact that it is mentioned in cppreference.com
would count as "proof" to me).
Aside from this, I used the last sample to check it with
-std=c++11
-std=c++11
/std:c++14
(/std:c++11
is not an available option.)All passed this check on CompilerExplorer.