问题
I have a class stats
with a template so that it can be flexible. I'm new to templates though, and I thought the point of them was to make it flexible around the user. So I feel like I'm doing something wrong seeing as I've hit a small wall.
#include <iostream>
#include <cstdio>
#include <iomanip>
template <typename T>
class stats
{
private:
int n;
T sum;
public:
stats()
{
this->n = 0;
this->sum = T();
}
void push(T a);
void print();
};
int main()
{
std::string tmp; // change type based on class type T
stats<std::string> s;
while (std::cin >> tmp) // while input is active...
{
s.push(tmp);
}
// Output & Formatting
s.print();
return 0;
}
template <typename T>
void stats<T>::push(T a)
{
this->sum += a;
++this->n;
}
template <typename T>
void stats<T>::print()
{
std::cout << std::left << std::setw(4) << "N" << "= " << n << '\n'
<< std::left << std::setw(4) << "sum" << "= " << sum << '\n';
}
From int main()
, ideally, I'd like tmp to not have to be changed by myself every time I wan to try a different type. Is that possible in C++?
回答1:
The idiomatic way would be to expose a type alias:
template <typename T>
class stats
{
public:
using value_type = T;
// ...
};
Then in your main:
int main()
{
stats<std::string> s;
decltype(s)::value_type tmp;
while (std::cin >> tmp)
{
s.push(tmp);
}
// ...
}
That way, tmp
will always take the type of T
.
To even simplify your main function, you can use an alias there too:
int main()
{
using stats_t = stats<std::string>;
stats_t s;
stats_t::value_type tmp;
while (std::cin >> tmp)
{
s.push(tmp);
}
// ...
}
回答2:
Another option for classes that don't provide a value_type
type of member is to use a function to extract the template type like
template <template <typename...> typename Type, typename... Ts>
auto get_first_template_parameter(Type<Ts...>) -> std::tuple_element_t<0, std::tuple<Ts...>>;
template <typename T>
using value_type = decltype(get_first_template_parameter(std::declval<T>()));
get_first_template_parameter
is a meta function and only used to get the first type of the template type so it doesn't need a body. The using statement then uses that so you can have a type like:
stats<std::string> s;
value_type<decltype(s)> tmp; // changes type based on class type T
while (std::cin >> tmp) // while input is active...
{
s.push(tmp);
}
来源:https://stackoverflow.com/questions/63907609/any-way-to-initialize-this-variable-based-on-class-template-type