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
How to Correctly and Standardly Compare Floats
Why Catch an Exception as Reference-To-Const
Why Can't Static_Cast Be Used to Down-Cast When Virtual Inheritance Is Involved
Difference in Performance Between Msvc and Gcc for Highly Optimized Matrix Multplication Code
Why Can't a Derived Class Call Protected Member Function in This Code
Round a Float to a Regular Grid of Predefined Points
Linux Allocator Does Not Release Small Chunks of Memory
Multithreaded Rendering on Opengl
How to Recover View Space Position Given View Space Depth Value and Ndc Xy
Addition of Two Chars Produces Int
Dynamic Aligned Memory Allocation in C++11
Why Is It Illegal to Take the Address of an Rvalue Temporary
How to Set a Timeout on Blocking Sockets in Boost Asio
How to Store Objects of Differing Types in a C++ Container
Implementing a No-Op Std::Ostream
Moving Elements from Std::Vector to Another One
Is There a Formula to Determine Overall Color Given Bgr Values? (Opencv and C++)