This should almost do what you want:
#include <iostream>
template <typename Algorithm>
class UnsignedCharFunction {
public:
typedef Algorithm algorithm_type;
static bool compute(const unsigned char i1, const unsigned char i2) {
return call(algorithm_type::do_compute, i1, i2);
}
private:
static bool call(
bool (*f)(const unsigned char, const unsigned char),
const unsigned char i1, const unsigned char i2) {
return f(i1, i2);
}
};
class GreaterThan : public UnsignedCharFunction<GreaterThan> {
friend class UnsignedCharFunction<GreaterThan>;
private:
static bool do_compute(const unsigned char i1, const unsigned char i2) {
return i1 > i2;
}
};
class Invalid : public UnsignedCharFunction<Invalid> {
friend class UnsignedCharFunction<Invalid>;
private:
#define N 2
#if N == 1
// Fails
static bool no_do_compute(const unsigned char i1, const unsigned char i2) {
return i1 >= i2;
}
#elif N == 2
// Fails
static bool do_compute(char i1, char i2) {
return i1 >= i2;
}
#endif
};
int main() {
std::cout << "A > B:" << GreaterThan::compute('A', 'B') << '\n'
<< "B > A:" << GreaterThan::compute('B', 'A') << '\n';
// If you comment next line, there will be no error.
Invalid::compute('A', 'B');
}
It is almost, due instantiation of templates - an compiler error will only show up, when the function is used.
Regarding inline:
volatile bool value;
int main() {
value = GreaterThan::compute('A', 'B');
}
00000000004005a0 <main>:
4005a0: movb $0x0,0x200aa5(%rip) # 60104c <value>
4005a7: xor %eax,%eax
4005a9: retq
4005aa: nopw 0x0(%rax,%rax,1)
The code will completely elided in this simple little program.
Another inline:
volatile bool value;
volatile unsigned char a;
volatile unsigned char b;
int main() {
value = GreaterThan::compute(a, b);
}
00000000004005a0 <main>:
4005a0: movzbl 0x200aa5(%rip),%edx # 60104c <b>
4005a7: movzbl 0x200a9f(%rip),%eax # 60104d <a>
4005ae: cmp %al,%dl
4005b0: setb %al
4005b3: mov %al,0x200a95(%rip) # 60104e <value>
4005b9: xor %eax,%eax
4005bb: retq
4005bc: nopl 0x0(%rax)
Both compiled with "g++ -std=c++11 -O3 -g"