Any way to initialize this variable based on class template type?

微笑、不失礼 提交于 2021-02-04 21:08:16

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!