C++ 如何使用';默认值';模板元编程中的值
我面临以下问题: 我有一些通用容器,可以对类型执行一些操作。为简单起见,这些操作在被请求时是线程安全的。并且,请求表示容器中的类型具有C++ 如何使用';默认值';模板元编程中的值,c++,templates,c++11,metaprogramming,C++,Templates,C++11,Metaprogramming,我面临以下问题: 我有一些通用容器,可以对类型执行一些操作。为简单起见,这些操作在被请求时是线程安全的。并且,请求表示容器中的类型具有typedef std::true\u type需要线程安全性 struct thread_safe_item { typedef std::true_type needs_thread_safety; /* */ }; struct thread_unsafe_item { typedef std::false_type needs_
typedef std::true\u type需要线程安全性代码>
struct thread_safe_item {
typedef std::true_type needs_thread_safety;
/* */
};
struct thread_unsafe_item {
typedef std::false_type needs_thread_safety;
/* */
};
template<typename TItem> container {
/* some algorithms, that are std::enable_if selected, according to needs_thread_safety */
};
但显然没有进行延迟评估,因为错误是错误C2039:“需要线程安全”:不是“线程不安全项目”的成员。
如何获得未指定参数的默认值
这是为了教育目的,所以我不需要不同的方法来解决这个问题
谢谢 您不能为此使用std::conditional
,因为这将始终解析其所有参数。您可以创建自己的谓词:
template <bool, class>
struct get_thread_safety;
template <class T>
struct get_thread_safety<true, T>
{
typedef typename T::needs_thread_safety type;
};
template <class T>
struct get_thread_safety<false, T>
{
typedef std::false_type type;
};
// Used like this:
typedef
typename get_thread_safety<
has_defined_thread_safety<TItem>::value,
TItem
>::type needs_thread_safety;
模板
结构获得线程安全;
模板
结构获取线程安全
{
typedef typename T::需要线程安全类型;
};
模板
结构获取线程安全
{
typedef std::false_type类型;
};
//这样使用:
类型定义
typename获取线程安全<
已定义线程安全::值,
滴度
>::类型需要线程安全性;
实际上,如果将std::enable\u与std::conditional
结合使用,则可以更轻松地执行此操作:
#include <iostream>
#include <type_traits>
// Classes to be checked against needs_thread_safety
struct A {};
struct B { typedef std::true_type needs_thread_safety; };
struct C { typedef std::false_type needs_thread_safety; };
// Checker helper
template<class T> class get_thread_safety
{
typedef char(&zero_size_t)[0];
template <class X> static typename std::enable_if<X::needs_thread_safety::value, char>::type check(int);
template <class X> static typename std::enable_if<!X::needs_thread_safety::value, zero_size_t>::type check(int);
template <class X> static zero_size_t check(...);
public:
typedef typename std::conditional<sizeof(check<T>(0)), std::true_type, std::false_type>::type type;
};
int main()
{
// Usage. Will print 0 1 0
std::cout << get_thread_safety<A>::type::value << std::endl;
std::cout << get_thread_safety<B>::type::value << std::endl;
std::cout << get_thread_safety<C>::type::value << std::endl;
return 0;
}
#包括
#包括
//要根据需要检查的类\u线程\u安全
结构A{};
结构B{typedef std::true_type需要_thread_safety;};
结构C{typedef std::false_type需要_thread_safety;};
//棋盘格助手
模板类获取线程安全
{
typedef char(&zero_size_t)[0];
模板静态typename std::enable_if::type check(int);
模板静态typename std::enable_if::type check(int);
模板静态零尺寸检查(…);
公众:
typedef typename std::conditional::type type;
};
int main()
{
//用法。将打印0 1 0
std::cout实际上,您可以懒洋洋地使用std::conditional
,您只需要避免在其模板参数列表中使用嵌套的typedef。对于false
案例(“默认值”),您还需要另一种回退类型:
模板
结构线程\安全\选择器
{
模板
结构已定义线程安全
{
typedef char yes[1];
typedef字符编号[2];
模板静态是&测试(类型名C::需要线程安全*);
模板静态无测试(…);
静态常量布尔值=sizeof(测试(0))==sizeof(是);
};
//这将是您的“默认值”
结构不是线程安全的{
typedef std::false_类型需要线程安全;
};
类型定义
类型名称std::条件<
已定义线程安全::值,
TItem,/::类型::需要线程安全需要线程安全;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
//懒洋洋地,在选择完成之后
};
通常我使用类型选择器来指定最终类的特定基类,其中基类包含适当的实现。+1,但也可以使用std::conditional
。而不是yes
和no
(以及sizeof
),您可以使用std::true_type
和std::false_type
作为返回类型(然后,decltype(test(0))::value
(如果需要)。
#include <iostream>
#include <type_traits>
// Classes to be checked against needs_thread_safety
struct A {};
struct B { typedef std::true_type needs_thread_safety; };
struct C { typedef std::false_type needs_thread_safety; };
// Checker helper
template<class T> class get_thread_safety
{
typedef char(&zero_size_t)[0];
template <class X> static typename std::enable_if<X::needs_thread_safety::value, char>::type check(int);
template <class X> static typename std::enable_if<!X::needs_thread_safety::value, zero_size_t>::type check(int);
template <class X> static zero_size_t check(...);
public:
typedef typename std::conditional<sizeof(check<T>(0)), std::true_type, std::false_type>::type type;
};
int main()
{
// Usage. Will print 0 1 0
std::cout << get_thread_safety<A>::type::value << std::endl;
std::cout << get_thread_safety<B>::type::value << std::endl;
std::cout << get_thread_safety<C>::type::value << std::endl;
return 0;
}
template<typename TItem>
struct thread_safety_selector
{
template<typename T>
struct has_defined_thread_safety
{
typedef char yes[1];
typedef char no[2];
template <typename C> static yes& test(typename C::needs_thread_safety*);
template <typename> static no& test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
// this would be your "default value"
struct not_thread_safe {
typedef std::false_type needs_thread_safety;
};
typedef
typename std::conditional<
has_defined_thread_safety<TItem>::value,
TItem, // <---- note, not using the typedef here
not_thread_safe
>::type::needs_thread_safety needs_thread_safety;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
// lazily, after the selection is done
};