Khu*_*dov 22 c++ type-traits variadic-templates c++11
我希望variadic模板参数必须唯一.我知道多继承时,不允许相同的类继承.
struct A{};
struct B: A, A{}; // error
Run Code Online (Sandbox Code Playgroud)
使用这个规则,我做了一些代码.
#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.
}
Run Code Online (Sandbox Code Playgroud)
但我的计划没有像我预期的那样工作.怎么了?
//更新://谢谢,我修复了我的错误://
// #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.
// }
//
Run Code Online (Sandbox Code Playgroud)
问:有人可以解释,为什么失败了?
UPDATE2:我以前的更新是非法的:)).法律形式,但它编制了O(N)时间.
#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;
}
Run Code Online (Sandbox Code Playgroud)
Die*_*ühl 12
传递指针base_all<U...>
仅需要存在声明base_all<U...>
.在不尝试访问定义的情况下,编译器将不会检测到该类型实际上是错误定义的.缓解该问题的一种方法是使用需要定义的参数base_all<U...>
,例如:
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;
}
Run Code Online (Sandbox Code Playgroud)
虽然上面回答了这个问题,但它无法编译:创建的多重继承不适合SFINAE考虑.我不认为你可以利用规则不允许从两次继承的相同基数.但相关测试可以采用不同的方式实现:
#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 , "!");
}
Run Code Online (Sandbox Code Playgroud)
小智 5
如果您有 C++17 编译器并且您的类型列表不是太大,那么使用折叠表达式只需 4 行代码即可完成。不过,该算法本身具有二次复杂度。
template<typename T, typename... Types>
constexpr bool are_types_unique_v = (!std::is_same_v<T, Types> && ...) && are_types_unique_v<Types...>;
template<typename T>
constexpr bool are_types_unique_v<T> = true;
Run Code Online (Sandbox Code Playgroud)