Reputation: 64672
I am attempting to write a function-template that infers most of its parameters for the purpose of a simple lookup table.
However, my efforts consistently get compiler errors. Here is my best attempt so far:
// A simple templated struct that maps one key to one value
template<typename KT, typename VT>
struct LookupTable
{
KT key;
VT value;
};
// A lookup function that searches an array for a match.
// returns NULL if key was not found.
// returns pointer to matching value when key is found.
//
// The first parameter is a Reference to an Array of T, with a specific size N
// In this example, the size is 12.
template<typename T, size_t N, typename KT, typename VT>
VT* Find(T<KT,VT> (&A)[N], KT key) // <== Multiple Errors on this line
{
VT* pFoundValue = NULL;
for (size_t i = 0; i < N; ++i)
{
if (key == A[i].key)
{
pFoundValue = &(A[i].value);
break;
}
}
return pFoundValue;
}
// Test the function with a simple example
int main(void)
{
LookupTable<std::string, int> calendar[] = {
{ "January", 31 },
{ "February", 28 },
{ "March", 31 },
{ "April", 30 },
{ "May", 31 },
{ "June", 30 },
{ "July", 31 },
{ "August", 31 },
{ "September", 30 },
{ "October", 31 },
{ "November", 30 },
{ "December", 31 }
};
const int* pDays = Find(calendar, std::string("May"));
if (pDays == NULL)
{
cout << "Invalid Month" << endl;
}
else
{
cout << "The month of May has " << *pDays << " Days" << endl;
}
_getch();
return 0;
}
The errors I get are all on the declaration of the Find
function
(marked with a comment):
1>error C2143: syntax error : missing ')' before '<'
1>error C2143: syntax error : missing ';' before '<'
1>error C2988: unrecognizable template declaration/definition
1>error C2059: syntax error : '<'
1>error C2059: syntax error : ')'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
It really appears that I've made all the parameters easy to infer from the function call.
Do I have a syntax error that I'm missing?
Upvotes: 1
Views: 151
Reputation: 1152
Try this format:
template<size_t N, typename KT, typename VT, template<typename, typename> class T>
Upvotes: 0
Reputation: 25409
This is a more compact, SFINAE-friendly version, that compiles. Note that I have declared the array parameter const
because it need not be modified.
#include <type_traits>
template<typename PairT,
typename KeyT = decltype(std::declval<PairT>().key),
typename ValueT = decltype(std::declval<PairT>().value),
std::size_t N>
const ValueT *
Find(const PairT (&array)[N], KeyT key)
{
for (auto& iter : array)
if (key == iter.key)
return &(iter.value);
return nullptr;
}
Of course, this can be further simplified using an STL algorithm, which will also avoid creating the std::string
temporary for the lookup key.
auto pred = [](const LookupTable<std::string, int>& cal){
return cal.key == "May";
};
auto pDays = std::find_if(std::begin(calendar), std::end(calendar), pred);
if (pDays == std::end(calendar))
std::cout << "Invalid Month" << std::endl;
else
std::cout << "May has " << (*pDays).value << " days" << std::endl;
Upvotes: 1
Reputation: 206557
Instead of
template<typename T, size_t N, typename KT, typename VT>
VT* Find(T<KT,VT> (&A)[N], KT key)
use
template<template <typename, typename> class T, size_t N, typename KT, typename VT>
//^^^^^^^^^^^^^^^^^^^ Need to indicate that T is a class template
VT* Find(T<KT,VT> (&A)[N], KT key)
Upvotes: 1
Reputation: 16737
In this:
template<typename T, size_t N, typename KT, typename VT>
VT* Find(T<KT,VT> (&A)[N], KT key)
you are trying to use T
as a template template parameter. The syntax is:
template<template <class, class> class T, size_t N, typename KT, typename VT>
VT* Find(T<KT,VT> (&A)[N], KT key)
Upvotes: 3