Search code examples
c++staticnamespacestemplate-specializationboost-test

Explicitly specializing template, static vs. duplicate symbols


In a bunch of legacy code I have inherited, unit tests are implemented using Boost.Test. To enable checking std::wstring and icu::UnicodeString for equality via BOOST_CHECK_EQUAL(), the original author implemented explicit template specializations for equal_impl():

// test_utils.hpp

#include <boost/test/unit_test.hpp>
#include <unicode/unistr.h>

namespace boost
{
namespace test_tools
{
namespace tt_detail
{

template<>
static
boost::test_tools::predicate_result equal_impl( const std::wstring & wleft, const icu::UnicodeString & uright )
{
    const icu::UnicodeString uleft = w2u( wleft );
    return uleft == uright;
}

template<>
static
boost::test_tools::predicate_result equal_impl( const icu::UnicodeString & uleft, std::wstring & wright )
{
    const icu::UnicodeString uright = w2u( wright );
    return uleft == uright;
}

}
}
}

Now, this construct labels the template specializations as static. I understand that old GCC versions accepted this, but today's versions (post-4.3-ish) reject it:

error: explicit template specialization cannot have a storage class

However, if I remove the static, I get multiple definition at link time. And I can't put everything in an anonymous namespace, can I, since I have to specialize the template in boost::test_tools::tt_detail?

I am at a loss on how to resolve this (short of a complete refactoring of all the tests to using a custom predicate instead of BOOST_CHECK_EQUAL())...?

Note that C++11 is, unfortunately, not an option at this point, as not all target platforms have appropriate compiler support yet.


Solution

  • Replace static with inline and it'll be ok.