Re: Bypass virtual function call when calling direcltly with a object/reference of that type?
Jamboree <tongari95@gmail.com> writes:
tuple<A, B, C> t;
t.get<0>().f() // f is declared as a virtual function, but we know it's
A::f definitely.
I just want to ask if I could make sure that the compiler will call
A::f without the virtual mechanism.
Though I think it really depends on the compiler implementation, but I
think modern compilers, especially Clang, should have ability to
figure that out.
gcc (4.5/4.6) seems to do that optimization in many cases[*], but
clang (2.8) doesn't when I tried it. Clang doesn't seem to support
c++0x / std::tuple out of the box, but even with std::pair or a simple
structure field, clang 2.8 always seems do an indirect call through
the virtual table (maybe there's an extra option or something you
need, I dunno).
[*] gcc 4.5 generates direct calls for members of std::pair or with a
field member, but not for elements of std::tuple; gcc 4.6 can do
it on std::tuple in some cases too.
Here's a table summarizing the results for the attached source file,
with "DIRECT" meaning "uses a direct jump to the actual function", and
"vcall" meaning "calls through the virtual table." "-" means "didn't
compile" (as clang 2.8 doesn't seem to support c++0x / std::tuple, at
least by default).
gcc-4.5 gcc-4.6 clang-2.8
--------------------------------------------------------
arg_tuple_test vcall vcall -
local_tuple_test vcall DIRECT -
extern_tuple_test vcall DIRECT -
arg_pair_test DIRECT DIRECT vcall
local_pair_test DIRECT DIRECT vcall
extern_pair_test DIRECT DIRECT vcall
arg_member_test DIRECT DIRECT vcall
local_member_test DIRECT DIRECT vcall
extern_member_test DIRECT DIRECT vcall
Compiler arguments used:
gcc-4.5: -DUSE_TUPLE -std=c++0x -O2 -march=native -S
gcc-4.6: -DUSE_TUPLE -std=c++0x -O2 -march=native -S
clang-2.8: -O2 -march=native -S
-Miles
Here's the source file, "x.cc":
---- start ----
#ifdef USE_TUPLE
#include <tuple>
#endif
#include <utility>
struct A
{
virtual void f () const;
};
struct X
{
A a;
};
#ifdef USE_TUPLE
void arg_tuple_test (const std::tuple<A> &t)
{
std::get<0>(t).f ();
}
void local_tuple_test ()
{
const std::tuple<A> t;
std::get<0>(t).f ();
}
void extern_tuple_test ()
{
extern const std::tuple<A> t;
std::get<0>(t).f ();
}
#endif
void arg_pair_test (const std::pair<A,A> &t)
{
t.first.f ();
}
void local_pair_test ()
{
const std::pair<A,A> t;
t.first.f ();
}
void extern_pair_test ()
{
extern const std::pair<A,A> t;
t.first.f ();
}
void arg_member_test (const X &t)
{
t.a.f ();
}
void local_member_test ()
{
X t;
t.a.f ();
}
void extern_member_test ()
{
extern const X t;
t.a.f ();
}
---- end ----
--
Admiration, n. Our polite recognition of another's resemblance to ourselves.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]