【发布时间】:2010-05-28 01:10:18
【问题描述】:
我有一个静态的 Utils 类。我希望模板化某些方法,但不是整个类。我该怎么做?
这失败了:
#pragma once
#include <string>
using std::string;
class Utils
{
private:
template<class InputIterator, class Predicate>
static set<char> findAll_if_rec(InputIterator begin, InputIterator end, Predicate pred, set<char> result);
public:
static void PrintLine(const string& line, int tabLevel = 0);
static string getTabs(int tabLevel);
template<class InputIterator, class Predicate>
static set<char> Utils::findAll_if(InputIterator begin, InputIterator end, Predicate pred);
};
错误:
utils.h(10): error C2143: syntax error : missing ';' before '<'
utils.h(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
utils.h(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
utils.h(10): error C2238: unexpected token(s) preceding ';'
utils.h(10): error C2988: unrecognizable template declaration/definition
utils.h(10): error C2059: syntax error : '<'
我做错了什么?正确的语法是什么?
顺便说一下,我也想将返回值模板化。所以而不是:
template<class InputIterator, class Predicate>
static set<char> findAll_if_rec(InputIterator begin, InputIterator end, Predicate pred, set<char> result);
我会:
template<class return_t, class InputIterator, class Predicate>
static return_t findAll_if_rec(InputIterator begin, InputIterator end, Predicate pred, set<char> result);
我将如何指定:
1) return_t 必须是某种集合
2) InputIterator 必须是迭代器
3) InputIterator 的类型必须与 return_t 的类型一起使用。
谢谢。
更新:对于那些说我应该使用 Java/C# 样式 Utils 类的命名空间 intsead 的人的回应,这是否是您正在寻找的更多内容:
Utils.h
#pragma once
#include <string>
#include <set>
using std::set;
using std::string;
namespace Utils
{
static void PrintLine(const string& line, int tabLevel = 0);
static string getTabs(int tabLevel);
template<class result_t, class Predicate>
set<result_t> Utils::findAll_if(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred);
};
Utils.cpp
#include "Utils.h"
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
void Utils::PrintLine(const string& line, int tabLevel)
{
string tabs = getTabs(tabLevel);
cout << tabs << line << endl;
}
string Utils::getTabs(int tabLevel)
{
string tabs;
while (tabLevel != 0)
{
tabs += "\t";
tabLevel--;
}
return tabs;
}
template<class result_t, class Predicate>
set<result_t> Utils::findAll_if(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred)
{
set<char> result;
return findAll_if_rec(begin, end, pred, result);
}
template<class result_t, class Predicate>
set<result_t> findAll_if_rec(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred, set<result_t> result)
{
InputIterator nextResultElem = find_if(begin, end, pred);
if (nextResultElem == end)
{
return result;
}
result.add(*nextResultElem);
return findAll_if_rec(++nextResultElem, end, pred, result);
}
这有很多编译器错误。我认为我没有正确使用 result_t 模板参数。
更新 2 基于 Georg 的 cmets:
Utils.h
#pragma once
#include <string>
#include <set>
using std::set;
using std::string;
namespace Utils
{
void PrintLine(const string& line, int tabLevel = 0);
string getTabs(int tabLevel);
template<class result_t, class Predicate>
set<result_t> Utils::findAll_if(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred);
};
namespace detail
{
template<class result_t, class Predicate>
set<result_t> findAll_if_rec(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred, set<result_t> result);
};
Utils.cpp
#include "Utils.h"
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
void Utils::PrintLine(const string& line, int tabLevel)
{
string tabs = getTabs(tabLevel);
cout << tabs << line << endl;
}
string Utils::getTabs(int tabLevel)
{
string tabs;
while (tabLevel != 0)
{
tabs += "\t";
tabLevel--;
}
return tabs;
}
set<result_t> Utils::findAll_if(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred)
{
set<char> result;
return findAll_if_rec(begin, end, pred, result);
}
set<result_t> detail::findAll_if_rec(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred, set<result_t> result)
{
InputIterator nextResultElem = find_if(begin, end, pred);
if (nextResultElem == end)
{
return result;
}
result.add(*nextResultElem);
return findAll_if_rec(++nextResultElem, end, pred, result);
}
仍然没有编译。帮忙?
更新 3: 越来越近了……
Utils.h:
#pragma once
#include <string>
#include <set>
using std::set;
using std::string;
namespace Utils
{
void PrintLine(const string& line, int tabLevel = 0);
string getTabs(int tabLevel);
template<class result_t, class Predicate>
set<result_t> Utils::findAll_if(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred)
{
set<result_t> result;
return findAll_if_rec(begin, end, pred, result);
}
}
namespace detail
{
template<class result_t, class Predicate>
set<result_t> findAll_if_rec(set<result_t>::iterator begin, set<result_t>::iterator end, Predicate pred, set<result_t> result)
{
set<result_t>::iterator nextResultElem = find_if(begin, end, pred);
if (nextResultElem == end)
{
return result;
}
result.add(*nextResultElem);
return findAll_if_rec(++nextResultElem, end, pred, result);
}
}
Utils.cpp:
#include "Utils.h"
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
void Utils::PrintLine(const string& line, int tabLevel)
{
string tabs = getTabs(tabLevel);
cout << tabs << line << endl;
}
string Utils::getTabs(int tabLevel)
{
string tabs;
while (tabLevel != 0)
{
tabs += "\t";
tabLevel--;
}
return tabs;
}
仍然无法编译。
【问题讨论】:
-
为什么不直接将其设为命名空间,甚至不将私有详细信息放在标头中?
-
请注意,编译器永远不会推断返回值——客户端必须明确指定模板参数。只是为了让你知道....
-
从文体上看,这看起来像是在尝试用 C++ 编写 Java。不要试图让一切都成为一个类。通常的 C++ 风格不是像这样的实用程序类,而是具有独立的函数,可能封装在命名空间中。 “公共”函数在头文件中声明并在实现文件中定义,“私有”函数仅在实现文件的匿名命名空间中。
-
@Boojum:匿名命名空间在这里不起作用,因为它们是模板。应该改用
detail命名空间之类的东西。 -
@Boojum:我尝试用 C++ 编写 Java 是绝对正确的。哈哈。