Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using an undeclared variable legal in a template function?

Tags:

Note: The original problem heavily uses macros, but it has been simplified for this question.

The question

// header.hpp template <typename T> void foo() {    someBoolean = true ; // at this point "someBoolean" wasn't }                       // declared 

Then, it is used in the following source:

// source.cpp #include "header.hpp"  static bool someBoolean = false ;  void bar() {    foo<char>() ; // here, we call/instantiate the function } 

In some compilers (Windows, previous Solaris) it works. And in the current C++11 enabled Solaris compiler, it fails, saying someBoolean is undefined.

According to the standard, can a templated code use a variable that will be (we hope!) declared later in the source?

The bonus question

The template is defined in a header that is expected to be included in multiple sources, each one having its own boolean variable, and instantiating the template.

It was expected, in each translation unit, the template would affect the static boolean variable of that translation unit.

Each instantiation of the template on one type (say "char") is thus expected to affect different variables.

Aren't we relying on undefined behavior, there?

like image 421
paercebal Avatar asked Apr 09 '15 14:04

paercebal


People also ask

How will you restrict the template for a specific datatype?

There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.

What is an undeclared variable Java?

Undeclared: It occurs when we try to access any variable that is not initialized or declared earlier using var or const keyword. If we use 'typeof' operator to get the value of an undeclared variable, we will face the runtime error with return value as “undefined”.

How do you declare a template function?

To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>( float original ); Template arguments may be omitted when the compiler can infer them.

Does function template work with string?

The template function works for int and char, but not float and string.


1 Answers

This has to do with two-phase lookup. The short version is that any names that do not depend on the template parameter (like someBoolean here) will be looked up at template definition time. That means that the Solaris compiler is correct in rejecting the code. someBoolean has not been defined before the template is defined.

Names that do depend on the template parameter (e.g. if you had written something like T::someBoolean = true) will be deferred to template instantiation time - very reasonably, since their validity can't be determined until the compiler knows what T is. MSVC is known for not implementing these two-phase semantics properly (at least historically), which is why your code works there. It is not correct C++ and not portable behaviour, though.

Section 14.6 of (unknown version of) the C++ standard (probably draft):

If a name does not depend on a template-parameter (as defined in 14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation.

(via @BenVoigt comment below)

like image 100
CAdaker Avatar answered Oct 08 '22 17:10

CAdaker