Re: enum v.s. static function in template class: which one is better?
Yechezkel Mett ha scritto:
On Dec 28, 5:40 pm, Alberto Ganesh Barbati <AlbertoBarb...@libero.it>
wrote:
Michael Aaron Safyan ha scritto:
1.) The enum version is often written as:
template<typename T, int id>
struct Foo
{
typedef T Type;
static const int value = id;
};
...
Additionally, on
compilers which support this, taking the address of Foo<T,id>::value
will compile but cause a linker error (with GCC), unless an external
definition of the variable "int Foo<T,id>::value" is provided.
You can also see this the other way round. As a static const data member
is an lvalue, you *can* take its address as long as you also provide a
definition of the member. OTOH, you can *never* take the address of an
enumerator or a value returned by a static function, no matter what,
because they are rvalues.
What if the value is passed by const reference? If I understand
correctly, with an enum or a static function it will work, copying the
value, but with a static variable the linker will complain if there is
no external definition. (True, ints aren't normally passed by const
reference, but it might happen in a template.)
The standard says that "The member shall still be defined in a namespace
scope if it is used in the program" (9.4.2/4). Unfortunately what
constitutes a "use" is not specified as clearly. Anyway, I believe you
understand correctly in the sense that passing the static member by
(const) reference should constitute a "use" and therefore should require
a definition.
Despite the obvious annoyance of requiring the definition, there is an
interesting thing to notice, consider this code:
struct S
{
enum { a = 0; }
static int b() { return 0; }
static const int c = 0;
};
void f(const int&);
f(S::a); // (1)
f(S::b()); // (2)
f(S::c); // (3)
Assuming f() is not inlined, in both cases (1) and (2) a temporary will
be created, initialized and its address passed to f(). However, in (3)
the address of S::c is just passed to f(). I don't expect the difference
to be significant, yet it might have some impact on specific
architectures. It's not at all obvious which approach is better. For
example, reading S::c might result in a cache miss, but there's one less
memory write. Just food for thought.
Ganesh
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]