Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9100089
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 17, 20262026-06-17T00:46:52+00:00 2026-06-17T00:46:52+00:00

I wanted to share a strange example with you guys that I stumbled upon

  • 0

I wanted to share a strange example with you guys that I stumbled upon and that kept me thinking for two days.

For this example to work you need:

  • triangle-shaped virtual inheritance (on member function getAsString())
  • member function specialization of a template class (here, Value<bool>::getAsString()) overriding the virtual function
  • (automatic) inlining by the compiler

You start with a template class that virtually inherits a common interface – i.e. a set of virtual functions. Later, we will specialize one of these virtual functions. Inlining may then cause our specilization to get overloooked.

// test1.cpp and test2.cpp
#include <string>

class ValueInterface_common
{
public:
  virtual ~ValueInterface_common() {}
  virtual const std::string getAsString() const=0;
};

template <class T>
class Value :
  virtual public ValueInterface_common
{
public:
  virtual ~Value() {}
  const std::string getAsString() const;
};

template <class T>
inline const std::string Value<T>::getAsString() const
{
  return std::string("other type");
}   

Next, we have to inherit this Value class and the interface in a Parameter class that itself needs to be templated as well:

// test1.cpp
template <class T>
class Parameter :
  virtual public Value<T>,
  virtual public ValueInterface_common
{
public:
  virtual ~Parameter() {}
  const std::string getAsString() const;
};

template<typename T>
inline const std::string Parameter<T>::getAsString() const
{
  return Value<T>::getAsString();
}

Now, do not(!) give the forward declaration of a specialization for Value for type equaling bool …

// NOT in: test1.cpp
template <>
const std::string Value<bool>::getAsString() const;

But instead simply give its definition like this …

// test2.cpp
template <>
const std::string Value<bool>::getAsString() const
{
  return std::string("bool");
}

.. but in another module (that’s important)!

And finally, we have a main() function to test what is happening:

// test1.cpp
#include <iostream>

int main(int argc, char **argv)
{
  ValueInterface_common *paraminterface = new Parameter<bool>();
  Parameter<int> paramint;
  Value<int> valint;
  Value<bool> valbool;
  Parameter<bool> parambool;

  std::cout << "paramint is " << paramint.getAsString() << std::endl;
  std::cout << "parambool is " << parambool.getAsString() << std::endl;
  std::cout << "valint is " << valint.getAsString() << std::endl;
  std::cout << "valbool is " << valbool.getAsString() << std::endl;
  std::cout << "parambool as PI is " << paraminterface->getAsString() << std::endl;

  delete paraminterface;

  return 0;
}

If you compile the code as follows (I placed it into two modules named test1.cpp and test2.cpp where the latter only contains the specialization and necessary declarations):

g++ -O3 -g test1.cpp test2.cpp -o test && ./test

The output is

paramint is other type
parambool is other type
valint is other type
valbool is bool
parambool as PI is other type

If you compile with -O0 or just -fno-inline – or also if you do give the forward declaration of the specialization – the result becomes:

paramint is other type
parambool is bool
valint is other type
valbool is bool
parambool as PI is bool

Funny, isn’t it?

My explanation so far is: Inlining is at work in the first module (test.cpp). The required template functions get instantiated but some just end up being inlined in the calls to Parameter<bool>::getAsString(). On the other hand, for valbool this did not work but the template is instantiated and used as a function. The linker then finds both the instantiated template function and the specialized one given in the second module and decides for the latter.

What do you think of it?

  • do you consider this behavior a bug?
  • Why does inlining work for Parameter<bool>::getAsString() but not for Value<bool>::getAsString() although both override a virtual function?
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-17T00:46:54+00:00Added an answer on June 17, 2026 at 12:46 am

    I speculate that you have an ODR problem, so there is little sense in guessing why some compiler optimization behaves differently from another compiler setting.

    In essence, the One Definition Rule states that the same entity should
    have the exact same definition throughout an application, otherwise the
    effects are undefined.

    The fundamental problem is that the code that doesn’t see the specialized version of your class template member function might still compile, is likely to link, and sometimes might even run. This is because in the absence of (a forward declaration of) the explicit specialization, the non-specialized version kicks in, likely implementing a generic functionality that works for your specialized type as well.

    So if you are lucky, you get a compiler error about missing declarations/definitions, but if you are really unlucky you get “working” code that does not what you intend it to do.

    The fix: always include (forward) declarations of all template specializations. It’s best to put those in a single header and include that header from all clients that call your class for any possible template argument.

    // my_template.hpp
    #include "my_template_fwd.hpp"
    #include "my_template_primary.hpp"
    #include "my_template_spec_some_type.hpp" 
    
    // my_template_fwd.hpp
    template<typename> class my_template; // forward declaration of the primary template
    
    // my_template_primary.hpp
    #include "my_template_fwd.hpp"
    template<typename T> class my_template { /* full definition */ };
    
    // my_template_spec_some_type.hpp
    #include "my_template_fwd.hpp"
    template<> class my_template<some_type> { /* full definition */ };
    
    // some_client_module.hpp
    #include "my_template.hpp" // no ODR possible, compiler will always see unique definition
    

    Obviously, you could reorganize the naming by making subdirectories for template specializations and change the include paths accordingly.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have two console apps, Query and Update, that share some functionality. I wanted
I want to share this odd but interesting situation I stumbled upon recently while
This is more a gotcha I wanted to share than a question: when printing
I already know the answer to this, but wanted to share with the community
I wanted to know how does FB sharer work. I wanted to share different
I just wanted to share this Query class and get your thoughts on it.
This app tracks my workout routine and I wanted to share it with a
I wanted to share with you guys a function I had created to see
I just wanted to share my stupidity and how I used up all the
Task: I wanted to create a simple share button which extends to a share

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.