knightrider knightrider - 3 months ago 7
C++ Question

How to declare a class based on type of another class

I am trying to create an instance of a templated class, based on the template type of another class. But I am getting the following error.

error: template argument 1 is invalid


Here is a minimal example to reproduce the error

template <typename IdType>
class GraphNode
{
IdType id;
};

template <typename IdType>
class Graph
{
public:
using NodeType = IdType;

GraphNode<IdType> nodes[100];
};

template <typename IdType>
class ProcessGraph
{
//some functions
};

template <typename IdType>
auto create_graph()
{
Graph<IdType> graph;
// populate graph here
return graph;
}

int main(int argc, char *argv[])
{
if(atoi(argv[1]))
const auto &graph = create_graph<int>();
else
const auto &graph = create_graph<unsigned long>();

auto processor = ProcessGraph<typename graph.NodeType>(); // The error occurs here
return 0;
}


Thanks for help

Answer

There are two problems in your code:

  1. The graph variable has a different type in the branches, and it is out of scope when declaring processor.

  2. The syntax to access an inner type alias is wrong.


You can retrieve the type of a variable x using decltype(x). Since graph is a reference, you need to remove the reference using std::remove_reference_t. Afterwards, you can use ::NodeType to retrieve the inner type alias.

if(atoi(argv[1]))
{
    const auto &graph = create_graph<int>();
    auto processor = ProcessGraph<
        std::remove_reference_t<decltype(graph)>::NodeType>();
}
else
{
    const auto &graph = create_graph<unsigned long>();
    auto processor = ProcessGraph<
        std::remove_reference_t<decltype(graph)>::NodeType>();
}

If you want to refactor the code to avoid repetition, place the code that initializes the processor variable in a template function that gets graph as a parameter (or that creates graph in its body with a user-defined type).

Comments