Reputation: 505
Consider this c++ code that works fine:
template <size_t N>
int check(std::array<unsigned char, N> buf){
std::cout << N << "-" << buf.size() << std::endl;
return 0;
}
int main (int argc, char *argv[])
{
std::array<unsigned char, 20> a;
std::array<unsigned char, 30> b;
std::array<unsigned char, 40> c;
check(a);
check(b);
check(c);
return 0;
}
Is it possible to explicitly instantiate "check" for N=20 and N=30, but disable any other implicit instantiation?
That means that I would like to get a compile time error if I use "check(c)",
Edit:
In fact I wanted to have the same implementation, so a template was the right choice, and I wanted to just have a compile time error if for some reason I instantiate it with a parameters that is not supposed to exist. Because of that the static_assert (c++11) solution looks the best, as complete for the problem and very human readable.
Upvotes: 0
Views: 97
Reputation:
If you are treating the arrays differently, a template is useless in your case. Just provide some overloads:
#include <array>
#include <iostream>
int check(std::array<unsigned char, 20> buf){
std::cout << "Handling an array of size 20\n";
return 0;
}
int check(std::array<unsigned char, 30> buf){
std::cout << "Handling an array of size 30\n";
return 0;
}
int check(std::array<unsigned char, 40> buf){
std::cout << "Handling an array of size 40\n";
return 0;
}
int main (int argc, char *argv[])
{
std::array<unsigned char, 20> a;
std::array<unsigned char, 30> b;
std::array<unsigned char, 40> c;
check(a);
check(b);
check(c);
// std::array<unsigned char, 0> d;
//error: no matching function for call to ‘check(std::array<unsigned char, 0ul>&)'
//check(d);
return 0;
}
Otherwise, if the code is the same, a static_assert is good choice (see @Joachim Pileborg comment)
Upvotes: 0
Reputation: 217085
An other way is to delete the function:
template <size_t N>
void check(std::array<unsigned char, N> buf) = delete;
void check(std::array<unsigned char, 20> buf)
{
std::cout << 20 << "-" << buf.size() << std::endl;
}
void check(std::array<unsigned char, 30> buf)
{
std::cout << 30 << "-" << buf.size() << std::endl;
}
Upvotes: 0
Reputation: 75688
There are a few ways of doing this.
One way would be:
template <size_t N>
typename std::enable_if<N == 20 || N == 30, int>::type
check(std::array<unsigned char, N> buf) {
//..
}
A few thoughts about choosing between this and static_assert
shown in the other answers:
static_assert
may be viewed by some as more clean, clear way of expressing your constraint than enable_if
static_assert
is part of the implementation. In more complex code this can even affect how the function overloads.static_assert
you get a clear message of what is wrong when the constraint isn’t satisfied.Upvotes: 2
Reputation: 21130
You can use static_assert
to throw a compile time error if N
is anything other than 20 or 30.
template <size_t N>
int check(std::array<unsigned char, N> buf)
{
static_assert(N == 20 || N == 30, "N must be 20 or 30.");
std::cout << N << "-" << buf.size() << std::endl;
return 0;
}
Upvotes: 4
Reputation: 50053
You can use static_assert
:
template <size_t N>
int check(std::array<unsigned char, N> buf){
static_assert(N==20 || N==30, "invalid value of N");
std::cout << N << "-" << buf.size() << std::endl;
return 0;
}
It will cause a compile time error for invalid values of N
. See it live.
Upvotes: 3