c++ - check variadic templates parameters for uniqueness -
i want variadic template parameters must unique. know when multi inheritance, identical classes inheritance not allowed.
struct a{}; struct b: a, a{}; // error
using rule, made little code.
#include <type_traits> template< class t> struct id{}; template< class ...t> struct base_all : id<t> ... {}; template< class ... t> struct is_unique { template< class ... u> static constexpr bool test( base_all<u...> * ) noexcept { return true; } template< class ... u> static constexpr bool test( ... ) noexcept { return false;} static constexpr bool value = test<t...>(0); }; int main() { constexpr bool b = is_unique<int, float, double>::value; // false -- why? constexpr bool c = is_unique< int, char, int>::value; // false static_assert( b == true && c == false , "!");// failed. }
but program not worked expected. what's wrong?
//update: //thanks, fix error: //
// #include <type_traits> // #include <cstddef> // // template< class ... u> struct pack{}; // // template< class t> struct id{}; // template< class t> struct base_all; // template< class ... t> struct base_all< pack<t...> > : id<t> ... {}; // // // // template< class ... t> // struct is_unique // { // template< class p, std::size_t = sizeof(base_all<p>) > // struct check; // // template< class ...u> // static constexpr bool test(check< pack<u...> > * ) noexcept { return true;} // // template< class ... u> // static constexpr bool test(...)noexcept { return false;} // // static constexpr bool value = test<t...>(0); // }; // // int main() // { // constexpr bool b = is_unique<int, float, double>::value; // true // constexpr bool c = is_unique< int, char, int>::value; // false // // static_assert( b == true && c == false , "!");// success. // } //
q: can explain, why it's failed?
update2: previous update illegal :)). legal form, compiled o(n) time.
#include <cstddef> #include <iostream> #include <type_traits> namespace mpl { template< class t > using invoke = typename t :: type ; template< class c, class i, class e > using if_t = invoke< std::conditional< c{}, i, e> >; template< class t > struct id{}; struct empty{}; template< class a, class b > struct base : a, b {}; template< class b , class ... > struct is_unique_impl; template< class b > struct is_unique_impl<b>: std::true_type{}; template< class b, class t, class ... u> struct is_unique_impl<b, t, u...> : if_t< std::is_base_of< id<t>, b>, std::false_type, is_unique_impl< base<b,id<t>>, u...> >{}; template< class ...t >struct is_unique : is_unique_impl< empty, t ... > {}; } // mpl int main() { constexpr bool b = mpl::is_unique<int, float, double>::value; constexpr bool c = mpl::is_unique< int, char, int > :: value; static_assert( b == true , "!"); static_assert( c == false, "!"); return 0; }
passing pointer base_all<u...>
merely requires existence of declaration of base_all<u...>
. without attempting access definition, compiler won't detect type ill-defined. 1 approach mitigate problem use argument requires definition of base_all<u...>
, e.g.:
template< class ...t> struct base_all : id<t> ... { typedef int type; }; // ... template< class ... u> static constexpr bool test(typename base_all<u...>::type) noexcept { return true; }
although above answers question, fail compile: multiple inheritance created isn't in suitable context considered sfinae. don't think can leverage rule on not allowing same base inherited twice. relevant test can implemented differently, though:
#include <type_traits> template <typename...> struct is_one_of; template <typename f> struct is_one_of<f> { static constexpr bool value = false; }; template <typename f, typename s, typename... t> struct is_one_of<f, s, t...> { static constexpr bool value = std::is_same<f, s>::value || is_one_of<f, t...>::value; }; template <typename...> struct is_unique; template <> struct is_unique<> { static constexpr bool value = true; }; template<typename f, typename... t> struct is_unique<f, t...> { static constexpr bool value = is_unique<t...>::value && !is_one_of<f, t...>::value; }; int main() { constexpr bool b = is_unique<int, float, double>::value; constexpr bool c = is_unique< int, char, int>::value; static_assert( b == true && c == false , "!"); }
Comments
Post a Comment