我有一个模板类item
,它存储各种类型的T
对象。它还在实例化/初始化中将属性附加到这些对象。
我想要实现的一件特别的事情是,每当item
看到一个const char *
,它就把它当作一个std::string
来存储。可以这样做,如下所示。
但在类型检查中,我发现从const char *
实例化的const char *
与从std::string
实例化的item
的类型仍然不同。请看最后一行注释false
,这是我想要做的true
。
#include <iostream>
#include <string>
#include <type_traits>
using namespace std;
template<typename T>
using bar = typename std::conditional<std::is_same<T, const char *>::value,
string, T>::type;
template<typename T>
class item
{
bar<T> thing;
// other attributes ...
public:
item(T t) : thing(t) {}
// other constructors ...
bar<T> what() const
{
return thing;
}
};
int main()
{
auto a = item("const char *"); // class template argument deduction (C++17)
auto b = item(string("string")); // class template argument deduction (C++17)
cout << std::boolalpha;
cout << (typeid(a.what()) == typeid(b.what())) << endl; // true
cout << (typeid(a) == typeid(b)) << endl; // false
}
我的问题是:是否可以对模板类item
item
进行任何更改,以便从 const char *
实例化的 item
与从E 233
std::string
**?**实例化的item
的类型相同
换句话说,我是否可以对模板类item
typeid(a) == typeid(b)
的设计做任何更改,以便typeid(a) == typeid(b)
的计算结果为true?
谢谢!
注意:这是之前关于模板函数的https://stackoverflow.com/questions/52235994/type-conversion-in-function-template-deduction的后续。但我认为有一些本质上不同的问题值得提出单独的问题。
编辑:我的目标是更改模板类item
(例如item
签名)的设计,而不是由用户提供的main
中的代码。我希望通过不要求用户在实例化中显式地提供item
类型,使T
用户的生活更容易。这是指通过C++17模板类、参数演绎或一些等效的解决方法来完成的。
更新:谢谢大家!特别感谢@xskxzr,它的一条线正好解决了我的问题。使用 用户定义的扣减指南 进行类模板参数推导,我甚至不需要在前面的代码中使用技术。我将更新后的代码放在下面进行比较。。
#include <iostream>
#include <string>
using namespace std;
template<typename T>
class item
{
// UPDATE: no bar<T> needed any more
T thing;
// other attributes ...
public:
item(T t) : thing(t) {}
// other constructors ...
// UPDATE: no bar<T> needed any more
T what() const
{
return thing;
}
};
item(const char *) -> item<std::string>; // UPDATE: user-defined deduction guide !
int main()
{
auto a = item("const char *"); // class template argument deduction (C++17)
auto b = item(string("string")); // class template argument deduction (C++17)
cout << std::boolalpha;
cout << (typeid(a.what()) == typeid(b.what())) << endl; // true
cout << (typeid(a) == typeid(b)) << endl; // UPDATE: now true !
}
发布于 2018-09-08 20:28:51
发布于 2018-09-08 20:14:05
不,您不能直接使用不同的模板论证使两个模板对象的类型相同。
但是为了达到你的最终目标,你可以使用类似于工厂的模式。它可能看起来像这样:
template<typename T, typename R = T>
item<R> make_item(T&& t)
{
return item<T>(std::forward<T>(t));
}
// Specialization for const char *
template<>
item<std::string> make_item(const char *&& str)
{
return item<std::string>(str);
}
这种方法的缺点是您需要用这个工厂来构造所有的对象。如果有很多异常,则需要对每个异常进行专门化处理。
发布于 2018-09-08 18:08:47
这与其说是答案,不如说是猜测,但我会说不。模板在编译时展开,因此因为您要创建一个
item<const char*>
和一个
item<std::string>
然后展开的代码看起来如下所示
class item1
{
bar<const char*> thing;
// other attributes ...
public:
item(const char* t) : thing(t) {}
// other constructors ...
bar<const char*> what() const
{
return thing;
}
};
class item2
{
bar<std::string> thing;
// other attributes ...
public:
item(std::string t) : thing(t) {}
// other constructors ...
bar<std::string> what() const
{
return thing;
}
};
(或多或少;它们实际上不会被称为item1和item2)
如何计算这两种类型取决于您,但对于编译器来说,它们实际上是两种不同的类型。
https://stackoverflow.com/questions/52240679
复制相似问题