我正在从C ++ Primer Plus做一个编程问题,要求我制作一个模板
返回数组中唯一元素数的函数。我不明白为什么
根据我的知识编译时,第13行导致错误,std :: string的行为类似于数组。
这是我的代码:
#include <iostream>
#include <set>
template <typename T>
int reduce(T ar[], int n);
int main()
{
long test[] = {1, 2, 1, 3, 3, 4, 1};
std::string testStr = "testing";
std::cout << reduce(test, 6) << std::endl;
std::cout << reduce(testStr, 7) << std::endl;
std::cin.get();
return 0;
}
template <typename T>
int reduce(T ar[], int n)
{
std::set<T> test;
for(int i = 0; i < n; i++)
{
test.insert(ar[i]);
}
return test.size();
}
答案 0 :(得分:4)
我立即回复std::string
不是数组,这就是C ++人员完成你正在寻找的任务的方式。
#include <iterator>
#include <iostream>
#include <set>
// instead of taking an array and length, just take where you want to start and where
// you want to stop.
template <typename TForwardIterator>
int reduce(TForwardIterator iter, TForwardIterator end)
{
// This is hideous syntax to get the type of object the iterator is describing.
// For std::string, it is char...for T*, it is T.
// I apologize for C++, I'm not sure there is a better way to do this.
typedef typename std::iterator_traits<TForwardIterator>::value_type value_type;
std::set<value_type> set;
// instead of forcing the objects to be an array type, use iterators!
for (; iter != end; ++iter)
set.insert(*iter);
return set.size();
}
int main()
{
long test[] = {1, 2, 1, 3, 3, 4, 1};
std::string testStr = "testing";
// begin() and end() are iterators you'll find on all the container types
std::cout << reduce(testStr.begin(), testStr.end()) << std::endl;
// pointers are iterators, too!
std::cout << reduce(test, test + 7) << std::endl;
return 0;
}
答案 1 :(得分:2)
答案很简单:std::string
不是数组。
只要您可以使用[]运算符访问元素,它就像一个数组,但它与char[]
的数据类型不同。事实上,该标准甚至不保证它像数组一样存储(意味着连续)。 T[]
只会匹配数组,而不是可以使用arraylike的对象。
为了解决这个问题,你有几个选择
reduce(teststr.c_str(), 7)
,因为c_str()
会返回带有字符串内容的字符。reduce
重写为template <typename T, typename U> int reduce(U ar, int n)
,并将其称为reduce<long>(test, 6)
和reduce<char>(testStr, 7)
。第二个模板参数是必需的,因为没有统一的方法从容器到元素(c ++ 0x /使用编译器扩展除外)。template <typename T>int reduce(T ar, int n)
和std::set<decltype(ar[0])> test;
(其余代码保持不变,不知怎的,我似乎有代码块部分有问题,所以这里只有这两行。当然在c ++中,人们通常会根据迭代器编写这样的函数(参见Travis Gockels的答案),因为这只是一种更灵活,更好的支持方式。
答案 2 :(得分:1)
您可能会将std :: strings与内置字符数组混淆。 std :: strings不是数组,虽然它们的行为与数组类似(该类有一个重载的[]运算符)并且包含数组(可以通过c_str()访问)。
如果用
替换第10行char testStr[] = "testing";
您的程序将编译并运行。
或者,您可以尝试以下方式:
#include <iostream>
#include <set>
template <typename T>
int reduce(const T* ar, int n);
int main()
{
long test[] = {1, 2, 1, 3, 3, 4, 1};
std::string testStr = "testing";
std::cout << reduce(test, 7) << std::endl;
std::cout << reduce(testStr.c_str(), testStr.size()) << std::endl;
std::cin.get();
return 0;
}
template <typename T>
int reduce (const T* ar, int n)
{
std::set<T> test;
for(int i = 0; i < n; i++)
{
test.insert(ar[i]);
}
return test.size();
}