Specialization of 'Template<Class _Tp> Struct Std::Less' in Different Namespace

Specialization of 'templateclass _Tp struct std::less' in different namespace

This is still the way to do it. Unfortunately you cannot declare or define functions within a namespace like you would do with a class: you need to actually wrap them in a namespace block.

warning: specialization of template in different namespace

Assuming that you are compiling this in C++11 mode (since clang gave no warning) and that this specialization is in the global namespace, then there's nothing wrong with your code. It's a g++ bug. §14.7.3 [temp.expl.spec]/p2:

An explicit specialization shall be declared in a namespace enclosing
the specialized template. An explicit specialization whose
declarator-id is not qualified shall be declared in the nearest enclosing namespace of the template, or, if the namespace is inline
(7.3.1), any namespace from its enclosing namespace set. Such a
declaration may also be a definition. If the declaration is not a
definition, the specialization may be defined later (7.3.1.2).

The global namespace is a "namespace enclosing the specialized template", and your declarator-id is qualified with std::, so the second sentence doesn't apply. As a workaround, you can do what cdhowie's answer suggests - i.e., opening a namespace std block and putting the specialization there.

See CWG issue 374 and GCC bug 56480.

Resolution of class template with different default template argument and partial specialization argument

If I understand the confusion, when you see

/* primary class template B */
template <int N, class = void>
struct B : std::false_type {};

/* partial specialization of B */
template <int N>
struct B<N, std::enable_if_t<(N != 0), int>> : std::true_type {};

You think that when the compiler sees B<1> in main,

  • it sees that the general template is ok,
  • then it goes to see the specialization and
    • sees that (N != 0) is true,
    • resolves std::enable_if_t<(N != 0), int> to int
    • thus resulting in B<1, int>, which is good and to be preferred since it is a specialization.

The story is slightly different.

The line

template <int N, class = void>

just means, as suggested in a comment, that when you write B<an-int> the compiler sees B<an-int, void>.

If you look at it from this perspective, you should see why the mismatch causes the behavior you observe: B<1> is just B<1, void>, and no specialization is targeting that.

Defining a template specialization in an anonymous namespace (and compile error C2888)

A symbol belonging to namespace std must be defined in a namespace that encloses std which means that you'll have to define it in the global namespace.

Here's an example from C2888:

namespace M {
namespace N {
void f1();
void f2();
}

void N::f1() {} // OK: namspace M encloses N
}

namespace O {
void M::N::f2() {} // C2888 namespace O does not enclose M
}

[temp.expl.spec/9] from the C++20 draft:

A template explicit specialization is in the scope of the namespace in which the template was defined. [ Example:

namespace N {
template<class T> class X { /* ... */ };
template<class T> class Y { /* ... */ };

template<>
class X<int> { /* ... */ }; // OK: specialization in same namespace

template<>
class Y<double>; // forward-declare intent to specialize for double
}

template<>
class N::Y<double> { /* ... */ }; // OK: specialization in enclosing namespace

template<>
class N::Y<short> { /* ... */ }; // OK: specialization in enclosing namespace

— end example ]

Partial specialization tempate c++

Look at this function declaration:

void frob(float f, bool g = true) {
// ...
}

As you might know, you can drop parameter name from declarations:

void frob(float f, bool = true) {
// ...
}

You can also set the default value using an expression. This is equivalent as the previous example:

void frob(float f, bool = std::is_floating_point<float>::value) {
// ...
}

Then, let's add a simple template for the sake of the exercise:

template<typename T>
void frob(T f, bool = std::is_floating_point<T>::value) {
// ...
}

Technically, you could move parameters to be template parameters, if you know them at compile time:

template<typename T, bool = std::is_floating_point<T>::value>
void frob(T f) {
// ...
}

Now it's beginning to look like your own template declaration isn't it?


Now that you understand the syntax, let's see how it's useful with partial specialization.

Imagine you're the compiler and you expand the template instantiation of ElementType for float and std::integral_constant<int, 0>:

template<>
struct ElementType<float, std::is_floating_point<float>::value> { ... };

template<>
struct ElementType<
std::integral_constant<int, 0>,
std::is_floating_point<int>::value
> { ... };

Expands the constants, you get this:

template<>
struct ElementType<float, true> { ... };

template<>
struct ElementType<std::integral_constant<int, 0>, false> { ... };

Now that you expanded this, you see that you have both true and false as the second parameter. You pick the specialization for each:

template<>
struct ElementType<float, true> { using Type = float; };

template<>
struct ElementType<std::integral_constant<int, 0>, false> {
// int
using Type = typename std::integral_constant<int, 0>::value_type;
};

namespace specialization in template class

using namespace is not allowed in class scope, nor is namespace alias. I don't think you can do a specialization that would somehow inject the namespace.

It's not exactly the same, but if it's an option to declare all the functions you need from that namespace in the specialization, you can make the function pointer as a member of that specialization:

template <names>
struct base_class;

template <>
struct base_class<names::first>
{
static constexpr auto test = &one::test;
};

template <>
struct base_class<names::second>
{
static constexpr auto test = &two::test;
};

template <names ns>
struct delcare_namespace : public base_class<ns>
{
delcare_namespace()
{
std::cout << this->test() << "\n";
}
};

How to define less than () operator or std::less struct for Eigen::Vector3f?

It is generally a really bad idea to use floating point values (or aggregates) as keys into a map.

That is a fundamental design issue. I mean, if there is a NaN, everything explodes. And two seemingly identical derivations of a floating point value can compare unequal.

But it isn't hard to write a comparison operator.

struct LexographicLess {
template<class T>
bool operator()(T const& lhs, T const& rhs) const {
return std::lexographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
};

then simply do:

std::map<Eigen::Vector3f, uint32_t, LexographicLess>;

we can fix the "NaN" issue:

template<class L=std::less<>>
struct LexographicLess {
template<class T>
bool operator()(T const& lhs, T const& rhs) const {
return std::lexographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), L{});
}
};

which lets us pass in a "sub-less", which we can harden against NaN issues.

Doing this right will depend on the framework of your problem. Does your space have to support locations that vary from layout of gates on a integrated circuit all the way to locations light years away? If not, you could reconsider using floating point values.

Second, spacial mapping using a one-dimensional ordered map like std::map is often a bad idea. Learn what a Quad and Octtree are, which organize things in 2 or 3 dimensions so that nearby things are nearby in the data structure.

The question "what are the values of this function near this coordinate" is far more sensible to ask of a continuum approximation (like 3 dimensional floats) than "what is the value stored for this exact point", which is near nonsense on a continuum, and doesn't work well in a floating point continuum approximation.

But that is far, far out of scope.



Related Topics



Leave a reply



Submit