如何专门化这个模板(注意返回类型)

发布于 2024-10-11 17:12:19 字数 356 浏览 1 评论 0原文

我想将以下 template: 专门化为

template <typename T, int P>
T item(size_t s);

类似的内容:

template<int P>
T item<typename T>(size_t s)
{
//for all numeric types
    return static_cast<T>(rand());
}

template <int P>
string item<string>(size_t s)
{
    return "asdf";
}

I'd like to specialize following template:

template <typename T, int P>
T item(size_t s);

into something like that:

template<int P>
T item<typename T>(size_t s)
{
//for all numeric types
    return static_cast<T>(rand());
}

template <int P>
string item<string>(size_t s)
{
    return "asdf";
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清醇 2024-10-18 17:12:19

您不能像这样部分专门化函数模板。模板部分特化仅适用于类模板。

但是,您可以使用 boost::enable_if 来“模拟”您正在寻找的函数模板部分专业化类型。

// Specialization for std::string
//
template <int P, typename T>
T item(size_t, typename boost::enable_if<boost::is_same<T, std::string> >::type* = 0)
{
   ....
}

// Specialization for int
//
template <int P, typename T>
T item(size_t, typename boost::enable_if<boost::is_same<T, int> >::type* = 0)
{
    ....
}

这样,如果您调用 item<5, std::string>(10) 您将调用第一个函数,如果您调用 item<5, int>(10)< /code> 您将调用第二个函数。

或者,如果您出于某种原因不想使用 Boost,另一种解决方法是创建一个调度程序类模板,当然可以对其进行部分专门化。

You can't partially specialize function templates like that. Template partial specialization is only for class templates.

However, you can use boost::enable_if to "emulate" the kind of function template partial specialization you're looking for.

// Specialization for std::string
//
template <int P, typename T>
T item(size_t, typename boost::enable_if<boost::is_same<T, std::string> >::type* = 0)
{
   ....
}

// Specialization for int
//
template <int P, typename T>
T item(size_t, typename boost::enable_if<boost::is_same<T, int> >::type* = 0)
{
    ....
}

This way, if you call item<5, std::string>(10) you'll invoke the first function, and if you call item<5, int>(10) you'll invoke the second function.

Alternatively, if you don't want to use Boost for some reason, another work-around is to create a dispatcher class template, which of course can be partially specialized.

最冷一天 2024-10-18 17:12:19

两者都需要部分专业化。第一个需要 SFINAE。由于函数模板只能完全专门化,因此您必须使用某种类型的辅助对象。

template <typename T, int P>
T item(size_t s);

template < typename T, typename Enable = void >
struct item_
{
  template < int P >
  T apply(size_t s);
};

template < typename T >
struct item_<T, typename enable_if< is_numeric<T> >::type >
{
  template < int P >
  static T apply(size_t s) { return static_cast<T>(rand()); }
};

template < >
struct item_<std::string, void>
{
  template < int P >
  static std::string apply(size_t s) { return "NSTHEOSUNTH"; }
};

template < typename T, int P >
T item(size_t s) { return item_<T>::template apply<P>(s); }

或者,您可以考虑标签分派:

struct numeric_tag {};
struct string_tag {};
struct wtf_tag {};

template < typename T, int P >
T item(size_t s, numeric_tag) { return static_cast<T>(rand()); }
template < typename T, int P >
T item(size_t s, string_tag) { return "SNTHEO"; }
template < typename T, int P >
T item(size_t s)
{
  item(s, if_
          < 
            is_numeric<T>
          , numeric_tag
          , typename if_
            <
              is_same< std::string, T >
            , string_tag
            , wtf_tag
            >::type
          >::type());
}

或者您可以混合一些元函数类以与标签匹配,并使用成对的向量...迭代它们,测试每个第一个(元函数类)并返回第二个(标签)以选择一个执行。

有很多很多很多方法可以解决这个问题。

Both are going to require partial specialization. The first is going to require SFINAE. Since function templates can only be fully specialized you'll have to use a helper object of some sort.

template <typename T, int P>
T item(size_t s);

template < typename T, typename Enable = void >
struct item_
{
  template < int P >
  T apply(size_t s);
};

template < typename T >
struct item_<T, typename enable_if< is_numeric<T> >::type >
{
  template < int P >
  static T apply(size_t s) { return static_cast<T>(rand()); }
};

template < >
struct item_<std::string, void>
{
  template < int P >
  static std::string apply(size_t s) { return "NSTHEOSUNTH"; }
};

template < typename T, int P >
T item(size_t s) { return item_<T>::template apply<P>(s); }

Alternatively you might consider tag dispatching:

struct numeric_tag {};
struct string_tag {};
struct wtf_tag {};

template < typename T, int P >
T item(size_t s, numeric_tag) { return static_cast<T>(rand()); }
template < typename T, int P >
T item(size_t s, string_tag) { return "SNTHEO"; }
template < typename T, int P >
T item(size_t s)
{
  item(s, if_
          < 
            is_numeric<T>
          , numeric_tag
          , typename if_
            <
              is_same< std::string, T >
            , string_tag
            , wtf_tag
            >::type
          >::type());
}

Or you could mix some metafunction classes up to match with tags and use a vector of pairs...iterate through them testing each first (the metafunction class) and returning the second (the tag) to pick an implementation.

There's lots and lots and lots of ways to go about it.

谁与争疯 2024-10-18 17:12:19

需要明确的是:您根本无法专门化函数模板。。你可以让它们超载,但不能专门化它们。

函数模板的部分特化(如果存在)的正确绑定将通过以下方式给出:

template<class T, class U> X f(T,U);

specialise template<class A, class B> X f(A,B) 
  with template <class K> <K,K*>;

模板类具有更简单的特化规范,因为它们由名称、函数重载唯一标识,因此这还不够。

Just to be clear: you cannot specialise function templates at all. You can overload them, you can't specialise them.

Correct binding of partial specialisations of function templates, if they existed, would be given by something like:

template<class T, class U> X f(T,U);

specialise template<class A, class B> X f(A,B) 
  with template <class K> <K,K*>;

Template classes have an easier specialisation specification because they're uniquely identified by name, functions overload, so that isn't enough.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文