У меня есть шаблон класса item
, в котором хранятся объекты различных типов T
. Он также присоединяет атрибуты к этим объектам в процессе создания / инициализации.
Одна особая вещь, которую я хочу достичь, это то, что всякий раз, когда item
видит const char *
, он считает и сохраняет его как std::string
. Это можно сделать следующим образом.
Но при проверке типов я обнаружил, что экземпляр item
, созданный из const char *
, по-прежнему отличается по типу от item
, созданный из std::string
. Пожалуйста, смотрите последнюю строку с комментарием 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
, созданный из std::string
Другими словами, могу ли я внести какие-либо изменения в дизайн класса шаблона item
, чтобы typeid(a) == typeid(b)
получил значение true?
Спасибо!
Примечание. Далее следует предыдущий вопрос о функции шаблона. Но я думаю, что есть нечто принципиально иное, что оно заслуживает отдельного вопроса.
Редактировать: Моя цель - изменить дизайн класса шаблона item
(например, item
подписей), а не кода в main
, который предполагается предоставлять пользователям. Я хочу упростить жизнь пользователям item
, не прося их явно указывать тип T
в экземплярах. Это должно быть сделано путем дедукции аргумента класса шаблона C ++ 17 или некоторых эквивалентных обходных путей.
Обновление: спасибо всем! Особая благодарность @xskxzr, чья однострочник точно решает мой вопрос. С определяемыми пользователем руководствами по выводу для вывода аргументов шаблона класса, мне даже не нужна техника bar<T>
в моем предыдущем коде. Я поместил обновленный код ниже для вашего сравнения.
#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 !
}