Reputation: 3
So I understand I could probably solve this problem by simply using a parameter pack, but that solution seems a little ugly to me. What I want to do is something like the following:
template<bool test>
void Foo(int x, int y, int z, /*if test is set to true*/ int w)
{
if constexpr(test)
{
//use w for something.
}
}
So basically use the template parameter to say whether the last parameter is required or not. If test is false and an argument is passed in for w then there should be a compilation error saying too many arguments were provided. Any ideas what is available to me to achieve something like this elegantly?
Upvotes: 0
Views: 82
Reputation: 4449
I think templates are the wrong tool for the job here. Instead you can use std::optional
to do what you're looking for:
#include <optional>
void Foo(int x, int y, int z, std::optional<int> w=std::nullopt) {
if (w) {
// use (*w) for something.
}
}
int main() {
Foo(1, 2, 3);
Foo(1, 2, 3, 100);
}
Upvotes: 0
Reputation: 10880
You might decouple interface from implementation, use overloads and enable_if
:
namespace detail
{
struct Empty {};
template<typename T>
void FooImpl(int x,int y, int z, T w)
{
constexpr test = std::is_same_v<T, Empty>;
if constexpr(test)
{
//use w for something
}
}
}
template<bool test>
std::enable_if_t<test> void Foo(int x, int y, int z, int w)
{
detail::FooImpl(x, y, z, w);
}
template<bool test>
std::enable_if_t<!test> void Foo(int x, int y, int z)
{
detail::FooImpl(x, y, z, detail::Empty{});
}
Note that in the generic case, you’d likely use std::forward<>
on the interface and perhaps document (using a static_assert()
) that the type of w
is Empty
or int
.
Upvotes: 1