如何为可以是字符或字符串的模板类实现方法?
Posted
技术标签:
【中文标题】如何为可以是字符或字符串的模板类实现方法?【英文标题】:how do i implement methods for a template class that can be either char or string? 【发布时间】:2020-02-04 15:53:19 【问题描述】:我有这门课
template <typename T>
class B
T x;
public:
B(char c)
if(typeid(x)==typeid(char)) x=c;
else
string h;
for(int i=0;i<10;i++) h.push_back(c);
x=h;
;
这是一个示例类,如果 x 的类型是 char 我希望 x=c 而如果 x 是字符串我希望 x 是 [c]^10
然后我尝试创建两个对象:
int main()
B<string> a('f');
B<char> b('g');
当 i 对象 b 被实例化时,编译器会在第 10 行产生错误:
[Error] cannot convert 'std::string aka std::basic_string<char>' to 'char' in assignment
我了解错误来自您无法将字符串分配给 char 的事实,但无论如何我都需要完成任务,我该怎么做?
【问题讨论】:
这看起来更像是两个不同的类而不是模板。 如果T
不是char
而不是std::string
,会发生什么?
@MarekR:模板不必处理所有类型,即使std::uniform_real_distribution
也只能处理float
/double
/long double
。
@Jarod42 我知道模板正在使用鸭子类型。问题的更多细节可以导致更合适的解决方案。
【参考方案1】:
对于 C++17,您可以使用 if constexpr
:
template <typename T>
class B
T x;
public:
explicit B(char c)
if constexpr (std::is_same_v<T, char>)
x = c;
else
// static_assert(std::is_same_v<T, std::string>);
x = std::string(10, c);
;
【讨论】:
如果你是 C++17,std::is_same_v<T, char>
也可以使用。【参考方案2】:
在 C++17 之前,这似乎是最简单的可能性:
#include <string>
template<class T>
class B
T x;
public:
B(char c);
;
template<>
B<char>::B(char c) : x(c)
template<>
B<std::string>::B(char c) : x(std::string(c,10))
int main()
B<char> a('a');
B<std::string> b('b');
//B<int> c('c'); // Linker error
【讨论】:
如果您使用-std=c++17
指定C++17 作为编译器标志,则最高投票也将起作用,假设您的编译器支持C++17。我提出这一点是因为您的陈述暗示 C++17 解决方案不起作用;确实如此。不过,实际指定标准由您自己决定。【参考方案3】:
如果 x 的类型是 char 我想要 x=c 而如果 x 是字符串我想要 x 是 [c]^10
一种方法是创建一个返回正确对象的函数模板。
// Declare the function template.
template <typename T> T make_data(char c);
Define specializations of the function template.
template <> char make_data<char>(char c)
return c;
template <> make_data<std::string>(char c)
return std::string(c, 10);
使用它们来实现B
。
template <typename T>
class B
T x;
public:
B(char c) : x(make_data<T>(c))
;
【讨论】:
我无法定义更多的函数、方法或成员 @GuglielmoLaMastra,这是一个相当不寻常的约束。至少要知道,当你在外面的世界时,不太可能施加这样的限制。【参考方案4】:简单的老式模板专业化:
template <typename T>
class B
T x;
public:
explicit B(char c) : x(c)
;
template <>
B<std::string>::B(char c) : x(10, c)
https://wandbox.org/permlink/5klGI0poD9mor4WY
【讨论】:
以上是关于如何为可以是字符或字符串的模板类实现方法?的主要内容,如果未能解决你的问题,请参考以下文章
(4.3)数组对象及类数组对象,set的用法,正则表达式的常用方法,蓝桥杯备赛-(生成数组数组去重实现模板字符串的解析新课上线啦)