abelenky
abelenky

Reputation: 64672

Inferring template parameters

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

Answers (4)

Gadi
Gadi

Reputation: 1152

Try this format:

 template<size_t N, typename KT, typename VT, template<typename, typename> class T>

Upvotes: 0

5gon12eder
5gon12eder

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

R Sahu
R Sahu

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

Pradhan
Pradhan

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

Related Questions