Answer computed at compile time (C++), 0 runtime overhead.
First the compiler generated code
; 147 : // Given a set of elements, find the one closest to the 1st element
; 148 : // ie, closest to 10
; 149 : int nNearest = ClosestInt_11<10, 45, 23, 63, 5, 8, 56, 74, 32, 96, 144, 95>::value;
mov DWORD PTR _nNearest$[ebp], 8
; 150 : // more values to test with
; 151 : nNearest = ClosestInt_11<-4, 45, 23, 63, 5, 8, 56, 74, 32, 96, 144, 95>::value;
mov DWORD PTR _nNearest$[ebp], 5
; 152 : nNearest = ClosestInt_11<144, 45, 23, 63, 5, 8, 56, 74, 32, 96, 144, 95>::value;
mov DWORD PTR _nNearest$[ebp], 144 ; 00000090H
; 153 : nNearest = ClosestInt_11<30, 45, 23, 63, 5, 8, 56, 74, 32, 96, 144, 95>::value;
mov DWORD PTR _nNearest$[ebp], 32 ; 00000020H
and the C++ Template code. Since TMP is new to me and they can't operate on array elements, ie no way to do recursion with array or string contents, this is a pretty heavy handed solution. Boost MPL makes this much easier to do.
#include "stdafx.h"
//////////////////////////////////////////////////////////////////////////
// Compile time IF THEN ELSE conditional
//////////////////////////////////////////////////////////////////////////
template<bool condition, int Then, int Else>
struct IF_THEN_ {
enum { value = Then };
};
template<int Then, int Else>
struct IF_THEN_<false, Then, Else> {
enum { value = Else };
};
//////////////////////////////////////////////////////////////////////////
// Compile time absolute value
//////////////////////////////////////////////////////////////////////////
template<int N>
struct ABS_
{
enum {
value = IF_THEN_<(N < 0), -N, N>::value
};
};
//////////////////////////////////////////////////////////////////////////
// Given N which is closer? n1 or n2
//////////////////////////////////////////////////////////////////////////
template<int N, int n1, int n2>
struct ClosestInt_2
{
enum {
/** Easier to read
//v1 = ABS_<n1 - N>::value,
//v2 = ABS_<n2 - N>::value,
//value = IF_THEN_<v1 < v2, n1, n2>::value
*/
// but probably more efficent
value = IF_THEN_< ABS_<n1 - N>::value < ABS_<n2 - N>::value, n1, n2 >::value
};
};
//////////////////////////////////////////////////////////////////////////
template<int N, int n1, int n2, int n3>
struct ClosestInt_3
{
enum { value = ClosestInt_2<N, n1, ClosestInt_2<N, n2, n3>::value>::value };
};
//////////////////////////////////////////////////////////////////////////
template<int N, int n1, int n2, int n3, int n4>
struct ClosestInt_4
{
enum {
value =
ClosestInt_2<N, n4, ClosestInt_2<N, n2,
ClosestInt_2<N, n2, n1>
::value>::value>::value
};
};
//////////////////////////////////////////////////////////////////////////
template<int N, int n1, int n2, int n3, int n4, int n5>
struct ClosestInt_5
{
enum {
value =
ClosestInt_2<N, n5, ClosestInt_2<N, n4, ClosestInt_2<N, n2,
ClosestInt_2<N, n2, n1>
::value>::value>::value>::value
};
};
//////////////////////////////////////////////////////////////////////////
template<int N, int n1, int n2, int n3, int n4, int n5, int n6>
struct ClosestInt_6
{
enum {
value =
ClosestInt_2<N, n6, ClosestInt_2<N, n5, ClosestInt_2<N, n4,
ClosestInt_2<N, n2, ClosestInt_2<N, n2, n1>
::value>::value>::value>::value>::value
};
};
//////////////////////////////////////////////////////////////////////////
template<int N, int n1, int n2, int n3, int n4, int n5, int n6, int n7>
struct ClosestInt_7
{
enum {
value =
ClosestInt_2<N, n7, ClosestInt_2<N, n6, ClosestInt_2<N, n5,
ClosestInt_2<N, n4, ClosestInt_2<N, n2, ClosestInt_2<N, n2, n1>
::value>::value>::value>::value>::value>::value
};
};
//////////////////////////////////////////////////////////////////////////
template<int N, int n1, int n2, int n3, int n4, int n5, int n6, int n7, int n8>
struct ClosestInt_8
{
enum {
value =
ClosestInt_2<N, n8, ClosestInt_2<N, n7, ClosestInt_2<N, n6,
ClosestInt_2<N, n5, ClosestInt_2<N, n4, ClosestInt_2<N, n2,
ClosestInt_2<N, n2, n1>
::value>::value>::value>::value>::value>::value>::value
};
};
//////////////////////////////////////////////////////////////////////////
template<int N, int n1, int n2, int n3, int n4, int n5, int n6, int n7, int n8, int n9>
struct ClosestInt_9
{
enum {
value =
ClosestInt_2<N, n9, ClosestInt_2<N, n8, ClosestInt_2<N, n7,
ClosestInt_2<N, n6, ClosestInt_2<N, n5, ClosestInt_2<N, n4,
ClosestInt_2<N, n2, ClosestInt_2<N, n2, n1>
::value>::value>::value>::value>::value>::value>::value>::value
};
};
//////////////////////////////////////////////////////////////////////////
template<int N, int n1, int n2, int n3, int n4, int n5, int n6, int n7, int n8, int n9, int n10>
struct ClosestInt_10
{
enum {
value =
ClosestInt_2<N, n10, ClosestInt_2<N, n9, ClosestInt_2<N, n8,
ClosestInt_2<N, n7, ClosestInt_2<N, n6, ClosestInt_2<N, n5,
ClosestInt_2<N, n4, ClosestInt_2<N, n2, ClosestInt_2<N, n2, n1>
::value>::value>::value>::value>::value>::value>::value>::value>::value
};
};
//////////////////////////////////////////////////////////////////////////
template<int N, int n1, int n2, int n3, int n4, int n5, int n6, int n7, int n8, int n9, int n10, int n11>
struct ClosestInt_11
{
enum {
value =
ClosestInt_2<N, n11, ClosestInt_2<N, n10, ClosestInt_2<N, n9,
ClosestInt_2<N, n8, ClosestInt_2<N, n7, ClosestInt_2<N, n6,
ClosestInt_2<N, n5, ClosestInt_2<N, n4, ClosestInt_2<N, n2,
ClosestInt_2<N, n2, n1>
::value>::value>::value>::value>::value>::value>::value>::value>::value>::value
};
};
void main()
{
// Given a set of elements, find the one closest to the 1st element
// ie, closest to 10
int nNearest = ClosestInt_11<10, 45, 23, 63, 5, 8, 56, 74, 32, 96, 144, 95>::value;
// more values to test with
nNearest = ClosestInt_11<-4, 45, 23, 63, 5, 8, 56, 74, 32, 96, 144, 95>::value;
nNearest = ClosestInt_11<144, 45, 23, 63, 5, 8, 56, 74, 32, 96, 144, 95>::value;
nNearest = ClosestInt_11<30, 45, 23, 63, 5, 8, 56, 74, 32, 96, 144, 95>::value;
}