This code compiles without any warnings or errors, and is executable.
template<class T>
struct testclass
{
template<int I>
class inner {};
template<int I>
void f(inner<I> ) {}
};
int main()
{
testclass<bool> test;
test.f(testclass<bool>::inner<3>()); // l. 13
return 0;
}
Now, what I'd like to do is to omit the testclass::
in line 13:
test.f(inner<3>());
It does not work. Is there anything that I can add in testclass
' definition, so that my code works?
C++11 is allowed.
In general, there is no global compiler flag that would allow such a deduction, because that would defeat name scoping.
However, you can typedef (or in case of a template - have a type alias) the inner class outside. In your case it would be:
template <int I> using inner = testclass::inner<I>;
This has to be written in global namespace, not within the testclass
.
Note that template alias is a feature of C++11
First, boilerplate.
Index boilerplate:
template<unsigned... Is> struct indexes {typedef indexes<Is...> type;};
template<unsigned Max, unsigned... Is> struct make_indexes:make_indexes<Max-1, Max-1, Is...> {};
template<unsigned... Is> struct make_indexes<0, Is...>:indexes<Is...> {};
A helper class to allow proxy construction without naming the enclosing class:
template<int I, typename... Args>
struct inner_helper {
std::tuple<Args...> args;
template<typename T, unsigned... Is>
T construct(indexes<Is...>) && {
return { std::forward<Args>(std::get<Is>(args))... };
}
template<typename T>
T construct() && {
return std::move(*this).template construct<T>( make_indexes<sizeof...(Args)>() );
}
};
A helper function to give you the syntax you want. Note that inner<3>
is now a function call rather than creating an object outside of the enclosing class scope:
template<int I, typename... Args>
inner_helper<I, Args...> inner( Args&&... args ) {
return {std::forward<Args>(args)...};
}
We augment testclass
with two overloads. One takes an inner_helper<int, Args...>
and constructs an inner<int>
using the Args...
, the other takes inner<int>
:
template<class T>
struct testclass
{
template<int I>
class inner {};
template<int I>
void f(inner<I> ) {}
template<int I, typename... Args>
void f(inner_helper<I, Args...> h) {
return f( std::move(h).template construct<inner<I>>() );
}
};
And finally, the requested syntax at point of use:
int main()
{
testclass<bool> test;
test.f(inner<3>()); // l. 13
return 0;
}
this lets you do the syntax you want (inner<3>()
), supports constructing said inner<3>
with arbitrary arguments (which get perfect-forwarded), and invokes your actual f(inner<I>)
method.
It does require that inner<I>
be move-constructable and implicitly constructable from the arguments to inner<I>
.
I am assuming that inner<I>
is a bit more complex than the type you used above. If it is not more complex, you should consider the SCARY technique of C++ iterators, where the iterator (while an internal type sortof) is actually an external type.
live example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With