I would like to let compiler deduce partially class template arguments from constructor.
The motivation is to write a protocol library where the existance (here the length in bits) of certain data depends of the value of last variable, so a conditional class must be used to model this.
The c++ code I want to implement should work like this, but I would like to implement it in a more expressive and simplified way, without having to set all the parameters in the template but leaving compiler deduce them:
Coliru link: https://coliru.stacked-crooked.com/a/bb15abb2a9c09bb1
#include <iostream>
template<typename T1, typename T2, typename F, int... Ints>
struct If : T1
{
const T2& condition;
constexpr If(const T2& cond) : condition(cond) {}
constexpr int bits() { return check() ? T1::bits : 0; }
constexpr bool check()
{
return (F{}(Ints, condition.value) || ...);
}
};
struct Variable1
{
int value{};
static constexpr int bits{ 5 };
};
struct Variable2
{
int value{};
static constexpr int bits{ 8 };
};
struct Datagram
{
Variable1 var1;
If<Variable2, Variable1, std::equal_to<int>, 1, 2> var2{ var1 };//It compiles and works OK under c++17. What I have...
//If<Variable2> var2{ var1, std::equal_to<int>{}, 1, 2 };// ...what I wish
};
int main()
{
Datagram data;
data.var1.value = 0;
std::cout << data.var2.bits() << "\n";//must be 0
data.var1.value = 1;
std::cout << data.var2.bits() << "\n";//must be 8
data.var1.value = 2;
std::cout << data.var2.bits() << "\n";//must be 8
}
Is this possible?