[英]Specializing template member function
I'm trying to specify a function of a template class, that should only work when an object of the class is created using specific types (KEY as std::string
and VALUE as std::string
). 我正在尝试指定模板类的功能,该功能仅在使用特定类型(KEY作为std::string
和VALUE作为std::string
)创建该类的对象时才起作用。
My template ( Dictionary.h
), simplified: 我的模板( Dictionary.h
),简化了:
#ifndef QB_DICTIONARY_H
#define QB_DICTIONARY_H
#include <map>
#include <string>
namespace QB {
template<typename KEY, typename VALUE, typename COMPARE = std::less<KEY>>
class Dictionary {
public:
typedef typename std::map<KEY, VALUE, COMPARE>::iterator iterator;
typedef typename std::map<KEY, VALUE, COMPARE>::const_iterator const_iterator;
Dictionary() {
}
Dictionary(const std::map<KEY, VALUE, COMPARE> & value) {
this->value = value;
}
typename iterator begin() {
return value.begin();
}
typename const_iterator begin() const {
return value.cbegin();
}
typename iterator end() {
return value.end();
}
typename const_iterator end() const {
return value.cend();
}
// Trying to have the function work only when the template KEY and VALUE are of type std::string
const std::string implode<std::string, std::string>(const std::string & valueSeparator, const std::string & pairSeparator) const {
std::string result;
for (iterator i = begin(); i != end(); i++) {
if (i != begin()) {
result += pairSeparator;
}
result += iterator->first;
result += valueSeparator;
result += iterator->second;
}
return result;
}
private:
std::map<KEY, VALUE, COMPARE> value;
};
}
#endif
The implode function is the one I'm trying to implement. implode函数是我要实现的函数。 Trying to compile the above results in this: 尝试编译以上结果:
1>d:\cloud storage\onedrive\projects\qb\qb\dictionary.h(115): error C2143: syntax error: missing ';' before '<'
1> d:\cloud storage\onedrive\projects\qb\qb\dictionary.h(133): note: see reference to class template instantiation 'QB::Dictionary<KEY,VALUE,COMPARE>' being compiled
1>d:\cloud storage\onedrive\projects\qb\qb\dictionary.h(115): error C2334: unexpected token(s) preceding '{'; skipping apparent function body
I'm not sure how I should implement this. 我不确定该如何实施。 Any hints? 有什么提示吗?
EDIT: 编辑:
I've encountered some new problems while trying out @TartanLlama's answer. 我在尝试@TartanLlama的答案时遇到了一些新问题。
My current code is as follows (irrelevant parts left out): Dictionary.h
: 我当前的代码如下(忽略了不相关的部分): Dictionary.h
:
#ifndef QB_DICTIONARY_H
#define QB_DICTIONARY_H
#include <map>
#include <string>
#include <type_traits>
namespace QB {
template<typename KEY, typename VALUE, typename COMPARE = std::less<KEY>>
class Dictionary {
public:
// ...
const std::string implode(const std::string &, const std::string &) const;
// ...
};
template<typename K=KEY, typename V=VALUE, typename COMPARE = std::less<KEY>>
std::enable_if_t<std::is_same<std::string, K>{} && std::is_same<std::string, V>{}, const std::string> Dictionary<K, V, COMPARE>::implode(const std::string & valueSeparator, const std::string & pairSeparator) const {
// ...
}
}
#endif
You can specialize by explicitly instantiate your method member like this outside your class definition : 您可以通过在类定义之外显式实例化方法成员来进行专门化:
template<> std::string QB::Dictionary<std::string, std::string>::implode(const std::string & valueSeparator, const std::string & pairSeparator) const {
std::string result;
for (const_iterator i = begin(); i != end(); i++) {
if (i != begin()) {
result += pairSeparator;
}
result += i->first;
result += valueSeparator;
result += i->second;
}
return result;
}
Note that I have fixed other errors (no need to add typename in return method type, use const_iterator...) 请注意,我已经修复了其他错误(无需在返回方法类型中添加typename,请使用const_iterator ...)
You are attempting to explicitly-specialize implode
, but it's not a template. 您正在尝试显式专业化implode
,但这不是模板。
You could use SFINAE to only enable the function if KEY
and VALUE
are std::string
: 如果KEY
和VALUE
是std::string
则可以使用SFINAE启用该功能:
template <typename K=KEY, typename V=VALUE>
std::enable_if_t<std::is_same<std::string, K>{} &&
std::is_same<std::string, V>{},
const std::string>
implode(const std::string & valueSeparator,
const std::string & pairSeparator) const {
//...
}
You could use static_assert
to issue an error if the function is instantiated for the wrong Dictionary
specialization: 如果为错误的Dictionary
专业化实例化了该函数,则可以使用static_assert
发出错误:
implode(const std::string & valueSeparator,
const std::string & pairSeparator) const {
static_assert(std::is_same<std::string, K>{} &&
std::is_same<std::string, V>{},
"KEY and VALUE must be std::string");
//...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.