为模板类专门化模板函数

发布于 2024-12-01 02:04:42 字数 1231 浏览 1 评论 0原文

我有一个索引器功能,并试图将其专门用于标准容器类型,但出现错误。我确信这要么简单,要么不可能,但我不记得是哪一个了。我更喜欢将它们作为函数对象,但我也无法使其工作。是否可以为模板类

namespace std { //declarations of predefined indexable types
    template <class T, class A> class vector;
    //others are here too, but all have the same issue 
}
//default indexer
template <class T>
double indexer(const T& b) { //this seems to work fine
    return b.getIndex();
}
// base types
template<> double indexer<char>(const char& b) { return double(b); }
//other primitives are here too, and work fine
// standard library
template<class T, class A> 
double indexer<std::vector<T,A>>(const std::vector<T,A>& b) 
{ return b.empty() ? 0 : indexer(*b.cbegin()); } //line with error

错误消息专门化模板函数:

error C2768: 'indexer' : illegal use of explicit template arguments

我希望这是专门化与重载,因为我有一个函数 A ,它接受函数对象/指针模板参数,并且重载函数 A 使用默认索引器调用第一个 A。

template<class T, class function>
double A(T a, function F) { return F(a);} //complicated
template<class T>
double A(T a) {return A(a, indexer<T>);} //default wrapper

这似乎很可能是一个重复的问题,但我似乎找不到一个。

I have an indexer function, and was attempting to specialize it for the standard container types, but get errors. I'm sure it's either simple or impossible, but I can't recall which. I would prefer these as a function-object, but I wasn't able to make that work either. Is it possible to specialize a template function for a template class

namespace std { //declarations of predefined indexable types
    template <class T, class A> class vector;
    //others are here too, but all have the same issue 
}
//default indexer
template <class T>
double indexer(const T& b) { //this seems to work fine
    return b.getIndex();
}
// base types
template<> double indexer<char>(const char& b) { return double(b); }
//other primitives are here too, and work fine
// standard library
template<class T, class A> 
double indexer<std::vector<T,A>>(const std::vector<T,A>& b) 
{ return b.empty() ? 0 : indexer(*b.cbegin()); } //line with error

error message:

error C2768: 'indexer' : illegal use of explicit template arguments

I would like for this to be specialization vs overloading, because I have a function A that takes a function object/pointer template parameter, and overloaded function A that calls the first A with a defaulted indexer.

template<class T, class function>
double A(T a, function F) { return F(a);} //complicated
template<class T>
double A(T a) {return A(a, indexer<T>);} //default wrapper

It seems highly likely this is a duplicate question, but I cannot seem to find one.

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

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

发布评论

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

评论(3

橘和柠 2024-12-08 02:04:42

您不能部分特化模板函数,只能特化模板类。

使用重载代替:

namespace std { //declarations of predefined indexable types
       template <class T, class A> class vector;
}
//default indexer
template <class T>
double indexer(const T& b) { return b.getIndex(); }

double indexer(const char& b) { return double(b); }

template<class T, class A>
double indexer(const std::vector<T,A>& b)
{ return b.empty() ? 0 : indexer(*b.cbegin()); }

You cannot partially specialize template functions, only template classes.

use overloading instead:

namespace std { //declarations of predefined indexable types
       template <class T, class A> class vector;
}
//default indexer
template <class T>
double indexer(const T& b) { return b.getIndex(); }

double indexer(const char& b) { return double(b); }

template<class T, class A>
double indexer(const std::vector<T,A>& b)
{ return b.empty() ? 0 : indexer(*b.cbegin()); }
清引 2024-12-08 02:04:42

由于函数不能部分专业化,因此我可以用函数对象替换索引器函数。这似乎工作正常,解决了我所有的问题。

namespace std { //declarations of predefined indexable types
    template <class T, class A> class vector;
}
template <class T>
struct indexer { 
    double operator()(const T& b) const 
    { return b.getIndex(); } 
};
template<> struct indexer<char> { 
    double operator()(const char& b) const 
    { return double(b); } 
};
template<class T, class A> struct indexer<std::vector<T,A>> { 
    double operator()(const std::vector<T,A>& b) const 
    { return b.empty() ? 0 : indexer(*b.cbegin()); } 
};

template<class T, class function>
double A(T a, function F) { return F(a);} //complicated
template<class T>
double A(T a) {return A(a, indexer<T>());} //default wrapper

Since functions cannot be partially specialized, I can replace the indexer functions with function objects. This seems to work fine, and solves all my problems.

namespace std { //declarations of predefined indexable types
    template <class T, class A> class vector;
}
template <class T>
struct indexer { 
    double operator()(const T& b) const 
    { return b.getIndex(); } 
};
template<> struct indexer<char> { 
    double operator()(const char& b) const 
    { return double(b); } 
};
template<class T, class A> struct indexer<std::vector<T,A>> { 
    double operator()(const std::vector<T,A>& b) const 
    { return b.empty() ? 0 : indexer(*b.cbegin()); } 
};

template<class T, class function>
double A(T a, function F) { return F(a);} //complicated
template<class T>
double A(T a) {return A(a, indexer<T>());} //default wrapper
山田美奈子 2024-12-08 02:04:42

这是一个仅基于重载的解决方案,使用 C++11 样式的可变参数模板:

template <typename T>
T print(const T & t)
{
  std::cout << t << std::endl;
  return t;
}

template <template <typename...> class Container, typename ...Args>
typename Container<Args...>::value_type print(const Container<Args...> & v)
{
  typedef typename Container<Args...>::value_type T;

  if (v.empty()) std::cout << "nil" << std::endl;
  else std::cout << *v.begin() << std::endl;

  return v.empty() ? T() : *v.begin();
}

如果您想要更花哨并且可以访问 is_container 类型特征(例如取自 漂亮打印机),您可以使用特定于容器的容器重载enable_if

template <template <typename...> class Container, typename ...Args>
typename std::enable_if<is_container<Container<Args...>>::value,
                        typename Container<Args...>::value_type>::type
print(const Container<Args...> & v)
{
  /* ... */
}

Here's a solution based solely on overloads, using C++11-style variadic templates:

template <typename T>
T print(const T & t)
{
  std::cout << t << std::endl;
  return t;
}

template <template <typename...> class Container, typename ...Args>
typename Container<Args...>::value_type print(const Container<Args...> & v)
{
  typedef typename Container<Args...>::value_type T;

  if (v.empty()) std::cout << "nil" << std::endl;
  else std::cout << *v.begin() << std::endl;

  return v.empty() ? T() : *v.begin();
}

If you want to be fancy and if you have access to an is_container type trait (e.g. taken from the pretty printer), you can make the container overload specific to containers, using enable_if:

template <template <typename...> class Container, typename ...Args>
typename std::enable_if<is_container<Container<Args...>>::value,
                        typename Container<Args...>::value_type>::type
print(const Container<Args...> & v)
{
  /* ... */
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文