Note that there are some explanatory texts on larger screens.

plurals
  1. POPossible to access private types in base classes via template indirection
    primarykey
    data
    text
    <p>I'm trying to, at compile time, select a type to use depending on whether one is publicly available in a given scope. It's best to go straight to the code:</p> <pre><code>#include &lt;iostream&gt; #include &lt;type_traits&gt; class Logger { std::string _p; public: Logger(std::string p): _p(p) { } void say(std::string message) { std::cout &lt;&lt; _p &lt;&lt; ' ' &lt;&lt; message &lt;&lt; std::endl; } }; struct Log { static Logger&amp; log() { static Logger _def("Default: "); return _def; } }; // 1. template &lt;typename P&gt; struct use_logger { static std::size_t test(P*); static char test(...); static const bool value = sizeof(test(reinterpret_cast&lt;P*&gt;(0))) == sizeof(std::size_t); }; class A { struct Log { static Logger&amp; log() { static Logger _def("A: "); return _def; } }; public: void say() { std::cout &lt;&lt; "A: " &lt;&lt; use_logger&lt;Log&gt;::value &lt;&lt; std::endl; std::conditional&lt;use_logger&lt;Log&gt;::value, Log, ::Log&gt;::type::log().say("From A"); } }; class B { public: void say() { std::cout &lt;&lt; "B: " &lt;&lt; use_logger&lt;Log&gt;::value &lt;&lt; std::endl; std::conditional&lt;use_logger&lt;Log&gt;::value, Log, ::Log&gt;::type::log().say("From B"); } }; class C : A { public: void say() { std::cout &lt;&lt; "C: " &lt;&lt; use_logger&lt;Log&gt;::value &lt;&lt; std::endl; //2. std::conditional&lt;use_logger&lt;Log&gt;::value, Log, ::Log&gt;::type::log().say("From C"); // Log::log().say("From C"); } }; class D : public A { public: void say() { // 2. std::cout &lt;&lt; "D: " &lt;&lt; use_logger&lt;Log&gt;::value &lt;&lt; std::endl; std::conditional&lt;use_logger&lt;Log&gt;::value, Log, ::Log&gt;::type::log().say("From D"); // Log::log().say("From C"); } }; int main(void) { { A i; i.say(); } { B i; i.say(); } { C i; i.say(); } { D i; i.say(); } } </code></pre> <p>My intention is that in <code>A</code>, there is a type <code>Log</code>, so that should be used rather than the global <code>::Log</code>, and in <code>B</code> where there is none, it should use the global <code>::Log</code>. Now both these work irrespective of <code>1.</code> (my incorrect test to see if the type is <em>private</em> in this scope..)</p> <p>The problem is in <code>C</code> and <code>D</code>, normally - without the test, <code>Log::log()</code> fails, because it's private in <code>A</code>. However if the <code>std::conditional&lt;&gt;</code> is used, there is no compilation error, and the output is incorrect as it is prefixed with <code>A:</code>. So, what have I missed (apart from the incorrect test - which I need to somehow fix...)? If nothing, then is this approach of exposing the private type in <code>A</code> using the <code>std::conditional</code> legal?</p> <p>EDIT: for sanity, I tested with the following:</p> <pre><code>std::conditional&lt;false, Log, ::Log&gt;::type::log("From C"); std::conditional&lt;false, Log, ::Log&gt;::type::log("From D"); </code></pre> <p>And it does use the global <code>::Log</code>, if it's true, it's somehow using the private <code>A::Log</code>.</p> <p>EDIT2: Infact this appears to be a more general condition, i.e. you can easily get access to some internal private types via a template indirection, e.g:</p> <pre><code>class F { struct Foo { void bar() { } }; }; template &lt;typename T&gt; struct ExposeInternal { typedef T type; }; int main(void) { { // We've got Foo! ExposeInternal&lt;F::Foo&gt;::type t; t.bar(); } { // Below fails F::Foo t; t.bar(); } } </code></pre> <p>EDIT 3: Okay - have confirmed, it is a reported GCC bug, nothing to do with <code>std::conditional</code>, not yet fixed in 4.7 or 4.8. <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47346" rel="nofollow">http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47346</a></p> <p>I will leave this question open for the moment.. will close it with the above later.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload