【问题标题】:C++: Templates for static functions?C++:静态函数的模板?
【发布时间】: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 是绝对正确的。哈哈。

标签: c++ templates syntax stl


【解决方案1】:

它抱怨返回类型--set&lt;char&gt;:你忘记包含&lt;set&gt; 并使用using std::set(或者最好在你使用它的地方输入std::set)。

作为强制模板参数满足某些要求,最简单的方法就是编写代码,使其假定类型满足这些要求。如果类型不满足这些要求,编译将失败。

【讨论】:

    【解决方案2】:

    如果你总是想返回集合,那么你可以让你的函数返回一个集合,其模板参数是你函数的模板参数:

    template<class set_t, class InputIterator, class Predicate>
    static std::set<set_t> findAll_if_rec(InputIterator begin, InputIterator end, Predicate pred, std::set<set_t> result);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-02
      相关资源
      最近更新 更多