I have some C++11 code using the auto
inferred type that I have to convert to C++98. How would I go about converting the code, substituting in the actual type f
As auto
is known at compile-time, you need to interoperate with the compiler.
One option would be the Clang compiler's LibTooling library that provides infrastructure that you can base static analysis tools on.
For example, look at their refactoring example code that removes superfluous .c_str()
calls from the code. I think you could write a similar tool that converts auto
into the inferred type.
You can try to use the BOOST_AUTO
macro in the Boost typeof library.
auto x = 5 + 7;
becomes
BOOST_AUTO(x,5+7);
It is going to be a PITA, but you can declare an incomplete struct template accepting a single type parameter.
Given the variable x
you want to know the type of, you can use the struct with decltype(x)
and that will lead to a compiler error that will show you the inferred type.
For example:
template<class Type> struct S;
int main() {
auto x = ...;
S<decltype(x)>();
}
Live demo
which will produce an error message in the form:
error: implicit instantiation of undefined template 'S<X>' (clang++)
error: invalid use of incomplete type 'struct S<X>' (g++)
with X
being the inferred type. In this particular case the type is int
.
Trivia: This has been recommended by Scott Meyer in one of the recent NDC 2014's videos (I don't remember which one).
You could use typeid and std::type_info::name();
#include <iostream>
#include <typeinfo>
#include <complex>
int
main()
{
using namespace std::literals::complex_literals;
auto x = 3.1415F;
std::cout << typeid(x).name() << '\n';
auto z = 1.0 + 1.0i;
std::cout << typeid(z).name() << '\n';
}
$ /home/ed/bin_concepts/bin/g++ -std=c++14 typeid.cpp
$ ./a.out
f
St7complexIdE
The names aren't beautiful but you can at least translate them. These names are got from g++. The name is compiler dependent. There is some movement to standardize a pretty_name(). Here is a non-standard way to unmangle the names.
An alternative approach would be to use function templates and type deduction. It may not work in all examples you have but it may help in some cases:
int foo ()
{
auto x = bar();
// do something with 'x'
}
Change this to:
template <typename T> int foo_(T x)
{
// do something with 'x'
}
int foo ()
{
foo_(bar());
}
auto
is specified in terms of type deduction, so the above should have very similar, if not identical semantics as the C++ '11 version.