I have a class Tester
which is inherited from class Usual
or Special
. It depends on a template parameter useSpecial
. By default, it uses Usual
, but if the user wants, he can use Special
instead.
This is my code:
#include <iostream>
#include <vector>
class Usual
{
protected:
int res() { return 0; }
};
class Special
{
protected:
int res() { return 1; }
};
enum class UseSpecial { No, Yes };
template<typename Container, UseSpecial useSpecial = UseSpecial::No>
class Tester : public
std::conditional_t<useSpecial == UseSpecial::No, Usual, Special>
{
public:
using ParentType = std::conditional_t<useSpecial == UseSpecial::No, Usual, Special>;
Tester(Container&& cont) : cont_(std::move(cont))
{}
int Call() { return ParentType::res() + cont_.size(); }
private:
Container cont_;
};
int main()
{
std::vector vec1{1.1, 2.2, 3.3};
Tester tester1(std::move(vec1));
std::vector vec2{1, 2, 3};
Tester<decltype(vec2), UseSpecial::Yes> tester2(std::move(vec2));
// std::vector vec2{1, 2, 3};
// Tester<true> tester2(std::move(vec2));
std::cout << tester1.Call() << std::endl;
std::cout << tester2.Call() << std::endl;
return 0;
}
Is there a way to make the commented lines work? Two lines above them of course works, but the type of the container can always be deduced, so I don't want to force the user to write it every time explicitly.
I have tried to write a deduction guide, but the problem is that the useSpecial
parameter can't be deduced from the constructor. Or, maybe, I need to somehow redesign the whole thing?
In real code, Usual
and Special
have lots of methods, and these methods are used identically in Tester
.
Class template argument deduction is all or nothing. You can't deduce Container
if you supply useSpecial
.
You can write an alias for special Tester
.
template <typename Container>
using SpecialTester = Tester<Container, UseSpecial::Yes>;
std::vector vec2{1, 2, 3};
SpecialTester tester2(std::move(vec2));