C++17 Class Template Partial Deduction

Partial class template argument deduction in C++17

You might add deduction guide as follow:

template<class T, class U>
Base(T, U) -> Base<T, U, bool>;

template<class V>
Base(V) -> Base<bool, int, V>;

which allows

Base val1(1, 4.); // Base<int, double, bool>
Base val2(5.); // Base<bool, int, double>

If you want to specify the "default" template, you might use the old way with make_

template <typename V, typename T, typename U>
Base<T, U, V> make_Base(T t, U u)
{
return Base<T, U, V>{t, u};
}

template <typename T, typename U, typename V>
Base<T, U, V> make_Base(V v)
{
return Base<T, U, V>{v};
}

auto val1 = make_Base<bool>(1, 4.); // Base<int, double, bool>
auto val2 = make_Base<bool, int>(5.); // Base<bool, int, double>

C++17 class template partial deduction

From this excellent trip report by Botond Ballo:

The feature as originally proposed included a provision for partial deduction, where you explicitly specify some of the template arguments, and leave the rest to be deduced, but this was pulled over concerns that it can be very confusing in some cases:

// Would have deduced tuple<int, string, float>,
// but tuple<int> is a well-formed type in and of itself!
tuple<int> t(42, "waldo", 2.0f);

C++17 Partial Deduction Guide

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.

partial class template argument deduction in C++

As mentioned in a comment, you can use a nested class such that the two parameters can be provided seperately (one explicitly the other deduced):

template<typename T1>
struct S {
template <typename T2>
struct impl {
T2 t2;
impl(const T2& _t2) : t2{_t2} {}
};

template <typename T2>
impl(const T2&) -> impl<T2>;
};

int main() {
S<int>::impl<double> s {3.14};
S<int>::impl s2 {3.14}; // <- T1 is provided in the angle brackets, T2 is deduced
}

I found this How to provide deduction guide for nested template class?. Though, the above code compiles without issues with both gcc and clang: https://godbolt.org/z/MMaPYGbe1.

If refactoring the class template is not an option, the helper function is a common and clean solution. The standard library has many make_xxx functions, some of them were only needed before CTAD was a thing.

Partial deduction of template parameter using constructor

I most often use a "type tag" to overcome this kind of problems. It also comes in handy for similar issues, like the lack of partial specialization of function templates.

#include <type_traits>

template<typename T> struct type_t{};
template<typename T> constexpr type_t<T> type;

template<class T1, class T2>
struct impl
{
impl(const T2& _t2, type_t<T1> = {}) : t2(_t2) {}

T1 t1;
const T2& t2;
};

int main()
{
int a{};
double b{};
impl<int, double> i(b);//This works...
impl j(b, type<int>); // This works as well
static_assert(std::is_same_v<decltype(j),impl<int, double>>);
}

Class template argument type deduction in C++17 - compilation problems

Your code is OK (but I suggest not to use using std::vector).

The problem is your compiler, g++ 6.3.0, that is too old to support the feature you're trying to use: class template argument deduction and deduction guides.

You need g++ 7 or newer.

Class template argument deduction before C++17

As mentioned in the comments, standardization of a feature takes a long time.

If you wish to know in detail about it, you can check out the section on Standardization from https://isocpp.org, particularly "The life of an ISO proposal: From “cool idea” to “international standard”".

The paper that eventually made CTAD possible in C++17 is titled Template Tidbits and was first published on 2012-09-22.

It underwent many revisions and the paper "Template argument deduction for class templates", which is the sixth revision of the paper was published on 2016-06-24.

So it took about five years for CTAD to go from “cool idea” to “international standard”.

Also as @StoryTeller notes, the idea itself has been around for a much longer time and is presented in the paper Argument Deduction for Constructors which was published in 2007.



Related Topics



Leave a reply



Submit