Reputation: 3
First of all I must say I am giving my first steps into C++ and I came from PHP so excuse this basic question. I been looking and testing many alternatives and I cannot seem to understand how to do this which in PHP would be something like distance($str1, $str2)
in order to read whatever the function distance
returns.
What I am trying to do is call a template which should return the Levenshtein distance between 2 strings.
Here is my code
template <class T> unsigned int edit_distance(const T& s1, const T& s2)
{
const size_t len1 = s1.size(), len2 = s2.size();
vector<vector<unsigned int> > d(len1 + 1, vector<unsigned int>(len2 + 1));
d[0][0] = 0;
for(unsigned int i = 1; i <= len1; ++i) d[i][0] = i;
for(unsigned int i = 1; i <= len2; ++i) d[0][i] = i;
for(unsigned int i = 1; i <= len1; ++i)
for(unsigned int j = 1; j <= len2; ++j)
d[i][j] = std::min( std::min(d[i - 1][j] + 1,d[i][j - 1] + 1),
d[i - 1][j - 1] + (s1[i - 1] == s2[j - 1] ? 0 : 1) );
return d[len1][len2];
}
string text1="house";
string text2="houses";
edit_distance <int> (text1, text2);
The problem is on line edit_distance <int> (text1, text2);
and the error Xcode is giving is: C++ requires a type specifier for all declarations
Again, I know this must be really basic, but I can not find the proper way of doing it. Any tip in the right direction will be much appreciated.
Thanks!
Upvotes: 0
Views: 401
Reputation: 20980
In
template <class T> unsigned int edit_distance(const T& s1, const T& s2)
the type T can be inferred directly from the arguments. So there's no need to specify the type at all. Just call
edit_distance(text1, text2);
from within a function. You can do this for any type supported by the template. If the type isn't supported, you'll get a compile-time error.
You need to explicitly specify a type only if it can't be inferred. And in your case, the type you specified, <int>
, didn't match the arguments you provided.
Upvotes: 1
Reputation: 88155
To test a suspision of mine I took your code, added the minimal includes and using declarations to allow the compiler to get to the call to edit_distance
and compiled it. Here is the complete contents of the file I compiled:
#include <vector>
#include <string>
#include <algorithm>
using std::vector;
using std::string;
template <class T> unsigned int edit_distance(const T& s1, const T& s2)
{
const size_t len1 = s1.size(), len2 = s2.size();
vector<vector<unsigned int> > d(len1 + 1, vector<unsigned int>(len2 + 1));
d[0][0] = 0;
for(unsigned int i = 1; i <= len1; ++i) d[i][0] = i;
for(unsigned int i = 1; i <= len2; ++i) d[0][i] = i;
for(unsigned int i = 1; i <= len1; ++i)
for(unsigned int j = 1; j <= len2; ++j)
d[i][j] = std::min( std::min(d[i - 1][j] + 1,d[i][j - 1] + 1),
d[i - 1][j - 1] + (s1[i - 1] == s2[j - 1] ? 0 : 1) );
return d[len1][len2];
}
string text1="house";
string text2="houses";
edit_distance <int> (text1, text2);
And my suspision checked out; I got the following error:
main.cpp:26:22: error: C++ requires a type specifier for all declarations
edit_distance <int> (text1, text2);
^~~~~
This is the exact error you mention, therefore I believe it's very likely you've made the same mistake as I included in my test source code. Most experienced programmers would just assume that your incomplete code is shown as it is for brevity, and would automatically insert some surrounding code that would completely avoid this error.
The thing you have not understood seems to be that in C++ code does not just go anywhere. C++ programs are not simply a series of statements that get executed as an interpreter reads them in the source.
C++ is a compiled language. The program is a series of declarations and definitions of functions, classes, etc. Statements, i.e. code that does stuff, goes only inside definitions. Your function call edit_distance<int>(text1, text2);
is not inside any definition, and therefore the compiler is not expecting a statement and has no idea what you're saying. So put it inside a definition. You probably want to use a function definition:
void foo() {
string text1="house";
string text2="houses";
edit_distance <int> (text1, text2);
}
Also, when the compiled code is executed the execution begins in a special entry point function, main. Only the code that is reachable through this entry point ever gets executed. (actually this isn't really true, but the other cases are irrelevant at the moment.)
Therefore, you need a main function that eventually leads to the code you want to execute. You could have main
call the above foo
, or you could just put your code directly in main
:
int main() {
string text1="house";
string text2="houses";
edit_distance <int> (text1, text2);
}
This code will still not compile, because the <int>
part is incorrect. The type inside the angle brackets becomes the type assigned to T
in the edit_distance function template:
template <class T> unsigned int edit_distance(const T& s1, const T& s2)
edit_distance<int>
says to set T equal to int:
unsigned int edit_distance(const int& s1, const int& s2)
And that's not what you want. You probably want to set T equal to string so that the s1 and s2 parameters are strings.
int main() {
string text1="house";
string text2="houses";
edit_distance<string>(text1,text2);
}
Next you probably want to actually see the return value. Add #include <iostream>
at the beginning of the source with your other includes, and then use the main function:
int main() {
string text1="house";
string text2="houses";
std::cout << edit_distance<string>(text1,text2) << '\n';
}
Upvotes: 1