简体   繁体   中英

C++17 Partial Deduction Guide

I am trying to write a deduction guide, that only detects one of many typename's from given constructor argument and requires user to enter int size manually

template <int size, typename T>
struct Board
{
            array<array<T, size>, size> values;

            explicit Board(const vector<T>& raw_values){

            }
};
template <int size, typename T> Board(const vector<T>&) -> Board<int size, T>;

The idea above is that user should still be forced to enter " int size " argument of template, but " typename T " should be deduced from the argument of constructor, is this possible?

After correct specification, this is how method should be called

auto b = Board<3>(initialStateVector);

Currently, it requires to me to enter like this;

auto b = Board<3, int>(initialStateVector);

So basically, I want " int " above to be deduced from given initialStateVector , which has type

const vector<int>& raw_values

The idea above is that user should still be forced to enter "int size" argument of template, but "typename T" should be deduced from the argument of constructor, is this possible?

According a note (and following examples) in this cppreference page

Class template argument deduction is only performed if no template argument list is present. If a template argument list is specified, deduction does not take place.

no, this isn't possible (not in C++17; we can hope in future versions of the standard).

If you want explicit the size and let deduce the type, the best I can imagine is pass through a good-old make_something function.

I mean something as follows (using std::size_t for the size, as in std::array and almost all STL)

template <std::size_t S, typename T>
Board<S, T> make_Board (std::vector<T> const & v)
 { return {v}; }

// ...

auto b = make_Board<3>(initialStateVector);

that should works also in C++11.

I came up with a workaround using a size hint object

template<int size>
struct SizeHint {};

Your class would take this as an additional constructor argument:

Board(SizeHint<size>, const std::vector<T>& raw_values)

You call the constructor like this:

auto b = Board(SizeHint<2>{}, v);

Bonus

This approach also works for type hints (my original motivation how I found this thread) :

template<typename T>
struct TypeHint{};

template<typename Result, typename T>
struct S {
    S(TypeHint<Result>, T arg) : t{arg}{}
    Result r() {return t;}
    T t;
};

#include <iostream>
int main() {
    S s{TypeHint<int>{}, 5.7};
    std::cout << s.r() << std::endl;
}

This can also be used in combination with variadic templates:

template<typename Result, typename... Args>
struct S {
    S(TypeHint<Result>, Args... args) : t{args...}{}
    std::tuple<Args...> t;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM