Home > Software engineering >  A template function as a template argument
A template function as a template argument

Time:06-30

How to make the pseudo code below compile?

#include <vector>

template <class T>
void CopyVector() { std::vector<T> v; /*...*/}

template <class T>
void CopyVectorAsync() { std::vector<T> v; /*...*/}

template <template <class> void copy()>
void Test()
{
    copy<char>();
    copy<short>();
    copy<int>();
}

int main()
{
    Test<CopyVector>();
    Test<CopyVectorAsync>();
}

CopyVector and CopyVectorAsync are the functions that copy some vector of elements of type T using different algorithms. Test function calls a given copy functions with different element types. main function calls CopyVector and CopyVectorAsync for all the element types.

CodePudding user response:

You can't have a template template parameter for function templates, only for class templates. Luckily we can make a class that looks rather like a function.

#include <vector>

template <class T>
struct CopyVector { void operator()() { std::vector<T> v; /*...*/} };

template <class T>
struct CopyVectorAsync{ void operator()() { std::vector<T> v; /*...*/} };

template <template <class> class copy>
void Test()
{
    copy<char>{}();
    copy<short>{}();
    copy<int>{}();
}

int main()
{
    Test<CopyVector>();
    Test<CopyVectorAsync>();
}

CodePudding user response:

You cannot pass overload set or functions template as (template) parameter.

You can pass template template parameter for classes:

template <template <class> class copy>
void Test()
{
    copy<char>{}();
    copy<short>{}();
    copy<int>{}();
}

template <class T>
struct CopyVector
{
    void operator()() const{ /*...*/}
};

int main()
{
    Test<CopyVector>();
}

or pass functor with template method.

template <typename copy>
void Test()
{
    copy{}.template operator()<char>();
    copy{}.template operator()<short>();
    copy{}.template operator()<int>();
}

template <class T>
void CopyVector() { /*...*/}

int main()
{
    auto lambda = []<typename T>(){ CopyVector<T>(); };
    Test<decltype(lambda)>();
}

Passing parameter by regular argument might allow "simpler" syntax:

template <typename T>
void Test(T f)
{
    f(std::type_identity<char>{});
    f(std::type_identity<short>{});
    f(std::type_identity<int>{});
}

template <class T>
void CopyVector(std::type_identity<T>) { /*...*/}

int main()
{
    Test([]<typename T>(std::type_identity<T>){ CopyVector<T>(); });
}
  • Related