4
#include <iostream>
#include <boost/static_assert.hpp>

using namespace std;

// I understand how the following template function works
// template <class T>
// T GetMax (T a, T b) {
//   T result;
//   result = (a>b)? a : b;
//   return (result);
// }    

// I have difficulties to understand how the following code works
// when we should use this syntax
template<int i> void accepts_values_between_1_and_10() {
  BOOST_STATIC_ASSERT(i >=1 && i < 10);
  cout << "i(between 1 and 10): " << i << endl;
}

// I created the following function to test the understanding of BOOST_STATIC_ASSERT
template<typename T> void accepts_values_between_1_and_10_alternative(T i) {
  BOOST_STATIC_ASSERT(i >=1 && i < 10);
  cout << "i(between 1 and 10): " << i << endl;
}

int main () {

  const int i = 5;
  accepts_values_between_1_and_10<i>();

  const int j = 6;
  accepts_values_between_1_and_10_alternative(j);

  return 0;
}

// $> g++ -o template_function -Wall -g template_function.cpp 
// template_function.cpp: In function ‘void accepts_values_between_1_and_10_alternative(T) [with T = int]’:
// template_function.cpp:33:48:   instantiated from here
// template_function.cpp:23:1: error: ‘((i > 0) && (i <= 9))’ is not a valid template argument for type ‘bool’ because it is a non-constant expression

Question1> what is the syntax behind the following statement? And when we should use it? If it is a template specialization, why we have to provide a parameter rather than just

template<int> void accepts_values_between_1_and_10()
instead of
template<int i> void accepts_values_between_1_and_10()

template<int> void accepts_values_between_1_and_10(int i)
instead of
template<int i> void accepts_values_between_1_and_10()

Question2> Is it true that we have to adopt this syntax at function scope then if we have to use this form?

Question3> How to correct the definition of accepts_values_between_1_and_10_alternative so that it works with BOOST_STATIC_ASSERT?

Thank you

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
q0987
  • 34,938
  • 69
  • 242
  • 387
  • 2
    Static-assert only works for compile-time constant expressions, e.g. template parameters. It does *not* work for ordinary function arguments. C++11 and C11 add the `static_assert` language construct, so you won't need Boost any more. – Kerrek SB Dec 25 '11 at 22:26

1 Answers1

5

Your template<typename T> void accepts_values_between_1_and_10_alternative(T i) is not compiling because runtime parameters are evaluated after templates have been instantiated. At function scope, the statement BOOST_STATIC_ASSERT(i >=1 && i < 10);, means that i is being looked up as a non-type template parameter. However, at the enclosing namespace scope, i is a runtime parameter for which only its type is looked up to instantiate int for T. But the value 6 (even though it is a constant expression in your program), is only evaluated after the template instantiation, and it is not visible at function scope during template argument deduction.

For your template<int i> void accepts_values_between_1_and_10(), the value of i is being looked up to instantiate 5 for i, and this value is propagated back to the BOOST_STATIC_ASSERT.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304