1

I tried the following code.

template <int VAL>
void printVAL()
{
    for(int i=0;i<VAL; i++){
        cout << " i value is "<<i<<endl;
    }
}

instantiation: printVAL<100>()

When i use (std::string s ) as a non type template parameter, the compiler shouted at me with the following error

"class std::basic_str<char>' is not a valid type for a template non-type parameter.

What i know is we should use only constant integral values only. Not even double.

Question:

1) why we should not use std::string, what bothers ?

2) What is the meaning of 'pointers to objects with external linkage can be used'. can i get any sample code for it?

Whoami
  • 13,930
  • 19
  • 84
  • 140
  • Where do you get the message in question 2 from? If asking a question about compilation or linker errors, it's always helpful to post the _complete_ and _unedited_ output. – Some programmer dude Apr 25 '13 at 12:23

4 Answers4

0

There are two types of templates: Templates for generic types, and templates with specified types.

The templates for generic types like like

template<typename T>

or

template<class T>

These templates can be used with just about any type. The actual usage of these types may limit the actual types that can be use though.

Templates with specified types are like the one you have in your question:

template<int VAL>

They can only be used with template arguments matching the specified type. In this case only integer literals can be used.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

You can only pass integral values as non-type template parameters. That's a limitation of the language. You probably want something as follows:

template<class T>
void printVAL(const T& t)
{
    for (auto& x : t) {
        cout << " x value is "<< x << '\n';
    }
}

This would print anything: containers, strings, arrays, etc.

0

According to 14.1/4,

A non-type template-parameter shall have one of the following (optionally cv-qualified) types:

  • integral or enumeration type,
  • pointer to object or pointer to function,
  • lvalue reference to object or lvalue reference to function,
  • pointer to member,
  • std::nullptr_t.

Your std::string is none of those.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

1) why we should not use std::string, what bothers ?

Compiler must be able to deduce and substitute template parameters at compile time. This can't be done with a std::string object, it could (and usualy does) change at runtime.

See also this Q&A.

2) What is the meaning of 'pointers to objects with external linkage can be used'. can i get any sample code for it?

That's because the address of an object with static storage duration (which object declared extern are) is a constant expression.

n3337 5.19/3, emphasis mine:

A literal constant expression is a prvalue core constant expression of literal type, but not pointer type. An integral constant expression is a literal constant expression of integral or unscoped enumeration type. [ Note: Such expressions may be used as array bounds (8.3.4, 5.3.4), as bit-field lengths (9.6), as enumerator initializ- ers if the underlying type is not fixed (7.2), as null pointer constants (4.10), and as alignments (7.6.2). —end note ] A converted constant expression of type T is a literal constant expression, implicitly converted to type T, where the implicit conversion (if any) is permitted in a literal constant expression and the implicit conversion sequence contains only user-defined conversions, lvalue-to-rvalue conversions (4.1), integral promotions (4.5), and integral conversions (4.7) other than narrowing conversions (8.5.4). [ Note: such expressions may be used as case expressions (6.4.2), as enumerator initializers if the underlying type is fixed (7.2), and as integral or enumeration non-type template arguments (14.3). —end note ] A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function. An address constant expression is a prvalue core constant expression of pointer type that evaluates to the address of an object with static storage duration, to the address of a function, or to a null pointer value, or a prvalue core constant expression of type std::nullptr_t. Collectively, literal constant expressions, reference constant expressions, and address constant expressions are called constant expressions.

Example you ask for:

#include <iostream>
#include <string>

extern std::string str; // not really neccesary

std::string str;

template<std::string* ptr>
struct S {
    S() { std::cout << ptr->length() << '\n'; }
    ~S() { std::cout << *ptr; }
};

int main()
{
    S<&str> s;
    str = "Hello world!";
}
Community
  • 1
  • 1
jrok
  • 54,456
  • 9
  • 109
  • 141