Testing a specific class name in different namespaces (SFINAE?)

Suppose I have several classes with the same name in different namespaces.

namespace A { class Foo { ... }; }
namespace B { class Foo { ... }; }
namespace C { class Foo { ... }; }

I would like to detect at compile time if the class is named Foodespite the namespace. For example, some class SFINAE,

template <typename T> struct is_Foo {
  static const bool value = /* some magic here */;
}; 

Then I want is_Foo<A::Foo>::valuetrue to is_Foo<B::Foo>::valuebe true and is_Foo<A::Bar>::valuefalse.

Then I would use is_Fooin static_assertor std::enable_if. Is it possible?

+4
source share
3 answers
template <typename T>
struct is_Foo : public std::false_type {
};

template <>
struct is_Foo<A::Foo> : public std::true_type {
};

template <>
struct is_Foo<B::Foo> : public std::true_type {
};

template <>
struct is_Foo<C::Foo> : public std::true_type {
};

, is_Foo<T> std::true_type T A::Foo .. std::false_type T. , SFINAE , .

static_assert enable_if.


is_Foo , "", . - . , , , T is_base_of .

+7

, , , @bolov, . , , , , . ideone.com:

#include <iostream>
#include <type_traits>

namespace A { class Foo {}; }
namespace B { class Foo {}; class Bar {}; }
namespace C { class Foo {}; }

template<typename T>
struct is_Foo: public std::integral_constant<bool,
    std::is_same<T, A::Foo>::value || std::is_same<T, B::Foo>::value || 
    std::is_same<T, C::Foo>::value> {};

int main() {
 std::cout << is_Foo<A::Foo>::value << ' ' << is_Foo<B::Foo>::value << ' ' 
           << is_Foo<C::Foo>::value << ' ' << is_Foo<B::Bar>::value 
           << std::endl;

 return (0);
}

:

1 1 1 0
+1

.

( ):

// declarations
template<typename T>
struct Foo_temp;

namespace A {
   struct tag;
   using Foo = Foo_temp<tag>;
}

namespace B {
   struct tag;
   using Foo = Foo_temp<tag>;
}

namespace C {
   struct tag;
   using Foo = Foo_temp<tag>;
}

// definitions
template<>
struct Foo_temp<A::tag> { /*...*/ };

template<>
struct Foo_temp<B::tag> { /*...*/ };

template<>
struct Foo_temp<C::tag> { /*...*/ };

// testing
template<typename T>
struct is_Foo : public std::false_type {};

template<typename T>
struct is_Foo<Foo_temp<T>> : public std::true_type {};

, Foo . , , , .., , is_Foo . , , , is_Foo (, Foo Foo), ( ), .

Foo (, ), .

, Foo_test , Foo_test, A,B,C. , , .

namespace A {
   struct tag;
   struct Foo_impl { /*...*/ };
   using Foo = Foo_temp<tag>;
}

//...

template<>
struct Foo_temp<A::tag> : A::Foo_impl {};

.

, Foo_temp tag (Foo_impl). , , , . , . a Bar.

, , , , , (, , ). : tag, , , .

template<typename T>
struct array<tag::dense, T> { /*...*/ };

template<typename T>
struct array<tag::sparse, T> { /*...*/ };

, is_array . . (. ). , . tag::lazy , .

0

Source: https://habr.com/ru/post/1532096/


All Articles