The following code doesn't work if class some_class
is templated. So my guess is that I have to put the template
specifier in front of something, but I don't really know where? I tried putting it in front of state::base and state::error types within the variant definition, but this doesn't work. Where do I put it and why?
#include <variant>
template <typename T>
class some_class
{
void do_something() {
struct state {
struct base{};
struct error{};
};
std::variant<state::base, state::error> fsm{};
}
};
int main() {}
Error:
<source>:12:47: error: type/value mismatch at argument 1 in template parameter list for 'template<class ... _Types> class std::variant'
12 | std::variant<state::base, state::error> fsm{};
| ^
<source>:12:47: note: expected a type, got 'some_class<T>::do_something()::state::base'
<source>:12:47: error: type/value mismatch at argument 1 in template parameter list for 'template<class ... _Types> class std::variant'
<source>:12:47: note: expected a type, got 'some_class<T>::do_something()::state::error'
CodePudding user response:
You need to use typename
to indicate that state::base
is a type
std::variant<typename state::base, typename state::error> fsm{};
CodePudding user response:
The compiler considers state::base
and state::error
to be dependent (on the template arguments), in which case they would require prefixing with typename
so that they are considered types while parsing the class template definition.
However, intuitively these names/types seem like they shouldn't be dependent. Although the type is a different one for each specialization of the enclosing class template, it is guaranteed that state::base
will always name and refer to a known type in the function definition for every instantiation of the enclosing template. This can't be changed e.g. via explicit or partial specialization.
This seems to be an open CWG issue (CWG 2074). The standard currently does not say that these names are dependent. They would be dependent only if the local classes contained a dependent type (see [temp.dep.type]/9.5), but they don't do that in your case. Still it seems some compilers consider these types to be dependent.
So your solution is to prefix them with typename
even if that is probably not required or intended per standard.