0

I'm having an error in my code that says the float and string data types aren't proper function calls for my template function. The template function works for int and char, but not float and string. I looked to see if there was errors in the function definitions, but I couldn't see any. Can someone explain or suggest what might be the problem?

Search.h

#ifndef Search_hpp
#define Search_hpp
#include <iostream>
#include <stdio.h>
using namespace std;
class Search{
private:
public:
    template<typename ST>
    ST LinearSearch(ST numbers[], int listSize, ST key);
    template<typename ST>
    ST BinarySearch(ST numbers[], int listSize, ST key);
};

#endif /* Search_hpp */

Search.cpp

#include "Search.h"
#include <iostream>
#include <string>
using namespace std;
template<typename ST>
ST Search::LinearSearch(ST numbers[], int listSize, ST key){
    int i;

    for (i = 0; i < listSize; ++i) {
        if (numbers[i] == key) {
            return i;
        }
    }

    return -1; /* not found */
}
template<typename ST>
ST Search::BinarySearch(ST numbers[], int listSize, ST key){
    int mid;
    int low;
    int high;

    low = 0;
    high = listSize - 1;

    while (high >= low) {
        mid = (high + low) / 2;
        if (numbers[mid] < key) {
            low = mid + 1;
        }
        else if (numbers[mid] > key) {
            high = mid - 1;
        }
        else {
            return mid;
        }
    }

    return -1; // not found

}

Main.cpp

#include "Search.h"
#include <iostream>
#include <string>
using namespace std;

int main() {
    int integerlist[] = {-1, 1, 5, 7, 8};
    float floatlist[] = {0.3338, 0.5, 2.5, 7.2, 9.6};
    string stringlist[] = {"anteater", "cat", "giraffe", "lion", "octopus"};
    char charlist[] = {'a', 'b', 'i', 'l', 'o' };
    const int size = 5;
    Search SearchClass;
    SearchClass.LinearSearch(integerlist, size, 12);
    SearchClass.BinarySearch(integerlist, size, 12);
    SearchClass.LinearSearch(floatlist, size, 6.543);
    SearchClass.BinarySearch(floatlist, size, 6.543);
    SearchClass.LinearSearch(stringlist, size, "lion");
    SearchClass.BinarySearch(stringlist, size, "lion");
    SearchClass.LinearSearch(charlist, size, 'o');
    SearchClass.BinarySearch(charlist, size, 'o');
};
Tarracon
  • 55
  • 5
  • 1
    What exactly is the error message? – Trass3r Nov 01 '18 at 01:18
  • No matching member function for call to 'LinearSearch' – Tarracon Nov 01 '18 at 01:30
  • 1
    That's not the complete error message... Anyways you should also run into linker errors later as your template implementation is in the cpp file. – Trass3r Nov 01 '18 at 01:42
  • @Trass3r raises a very important point. More on that in [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – user4581301 Nov 01 '18 at 01:50
  • Implementing them in the cpp is possible and of value if you know the set of types up front. You can/have to use explicit instantiation then. – Trass3r Nov 01 '18 at 04:39

2 Answers2

3

LinearSearch cannot be found because of ambiguity in the type deduction for the template parameter ST

In

SearchClass.LinearSearch(floatlist, size, 6.543);

type float is inferred for ST from floatlist but double is inferred from 6.543

Solution:

SearchClass.LinearSearch(floatlist, size, 6.543F);
                                               ^
                                        change made here

for force float for both.

SearchClass.LinearSearch(stringlist, size, "lion");

is similar. string is inferred from stringlist, but "lion" is a const char[5]

SearchClass.LinearSearch(stringlist, size, string("lion"));

solves that by transforming "lion" into a string.

Unfortunately then LinearSearch tries to return the index of the found item (or -1 if not found) as a string. As suggested by forthe's answer, returning string for an index is kind of silly, as is returning anything but an integer type.

int Search::LinearSearch(ST numbers[], int listSize, ST key)

seems more appropriate.

Additional notes:

Trass3r raises a very important point in the comments. Templates only be implemented in the header file.

The magic number 5 in

const int size = 5;

can be replaced with

SearchClass.LinearSearch(integerlist, size(integerlist), 12);

as of C++17. Documentation on std::size.

Community
  • 1
  • 1
user4581301
  • 33,082
  • 7
  • 33
  • 54
  • I understand thank you, but quick question, Why is "lion" being read as a const char[5]? – Tarracon Nov 01 '18 at 01:42
  • @Tarracon `"lion"` is a [string literal](https://en.cppreference.com/w/cpp/language/string_literal), and not a `std::string`. Wish I had a better documentation link than that. Everything else I've found either is harder to read or tries to explain that it isn't a pointer. – user4581301 Nov 01 '18 at 01:45
  • Huzzah! Microsoft's discussion of string literals is an easier read: [C String Literals](https://learn.microsoft.com/en-us/cpp/c-language/c-string-literals?view=vs-2017) Refer to the earlier CPP Reference link for the differences on how this works and the options available in C++. – user4581301 Nov 01 '18 at 01:56
1

The problem is that your template functions are declared to return the type specified, but if it's not found, it returns -1. -1 is not a string value, so the code fails. A solution would be to change the return type to size_t or similar, as you will only be returning indices.

forthe
  • 378
  • 3
  • 15
  • What would be the best way to implement that? Should I do a typecast to convert a variable into the passed data type? – Tarracon Nov 01 '18 at 01:34
  • 1
    You're returning the index or -1. You aren't ever returning the actual element. Your return type shouldn't be `ST` but a numeric type. – Daniel H Nov 01 '18 at 02:00