Partialtemplatedeductioninconstructors

Problem: I'm often in a situation where some types can be deduced from the constructor's arguments, but not all:

template <typename Res, typename Arg>
struct adder {
    adder (Arg a1, Arg a2) : a1 {a1}, a2 {a2} {}
    void compute () { res = a1 + a2; }
    Res result () { return res; }

    Arg a1, a2;
    Res res;
};

If I'm using int arguments and want to specify unsigned as result type, I would like to write something like:

auto add = adder<unsigned>(42, -51);

…which doesn't work. However, I don't want to explicitly mention int.

Candidate solutions: I can think of two ways to "make it work", first with a maker:

template <typename Res>
struct wrapper {
    template <typename Arg>
    static auto make_adder (Arg a1, Arg a2) {
      return adder<Res, Arg> (a1, a2);
    }
};

auto add = wrapper<unsigned>::make_adder (42, -51);

Second by making sure that all types can be deduced in the constructor:

template <typename Res, typename Arg>
struct adder_extra {
    adder_extra (Arg a1, Arg a2, Res r) : a1 {a1}, a2 {a2} {}
    void compute () { res = a1 + a2; }
    Res result () { return res; }

    Arg a1, a2;
    Res res;
};

auto add = adder_extra (42, -51, (unsigned) 0);

Question: Is there a preferred way? Can this be solved more neatly in another fashion?

回答

An option you did not mention is to do as the standard library does1, and free the maker function:

template <typename Res, typename Arg>
auto make_adder (Arg a1, Arg a2) {
      return adder<Res, Arg> (a1, a2);
}

Template argument deduction for functions allows one to specify part of the template arguments. make_adder<unsigned>(42, -51) is perfectly valid, as far back as C++98.

It's a workaround as well, true. But it's a prevalent and idiomatic one.


1 - std::make_unique, std::make_shared, std::make_optional, std::make_any, std::make_tuple, etc.


以上是Partialtemplatedeductioninconstructors的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>