我想根据给定的类型为std::uniform_*_distribution
制作特征。 E.g:
distribution_traits<float>::type int_dist;
我尝试了以下方法,但没有一个编译,我不知道为什么。
实施1
将std::enable_if
与typedef
s:
template <typename T>
struct distribution_traits {
using type = typename std::enable_if<std::is_integral<T>::value, std::uniform_int_distribution<T>>::type;
using type = typename std::enable_if<std::is_floating_point<T>::value, std::uniform_real_distribution<T>>::type;
};
Clang 3.4抱怨:
dist_traits.cpp:7:9: error: redefinition of 'type'
using type = typename std::enable_if<std::is_floating_point<T>::value, std::uniform_real_distribution<T>>::type;
^
dist_traits.cpp:6:9: note: previous definition is here
using type = typename std::enable_if<std::is_integral<T>::value, std::uniform_int_distribution<T>>::type;
^
dist_traits.cpp:6:40: error: no type named 'type' in 'std::enable_if<false, std::uniform_int_distribution<float> >'; 'enable_if' cannot be used to
disable this declaration
using type = typename std::enable_if<std::is_integral<T>::value, std::uniform_int_distribution<T>>::type;
^~~~~~~~~~~~~~~~~~~~~~~~~~
dist_traits.cpp:28:3: note: in instantiation of template class 'distribution_traits<float>' requested here
distribution_traits<float>::type int_dist;
^
2 errors generated.
实施2
使用enable_if
作为类模板参数:
template <typename T, typename distribution_t = void>
struct distribution_traits;
template <typename T>
struct distribution_traits<
T, typename std::enable_if<std::is_integral<T>::value,
std::uniform_int_distribution<T> >::type > {
using type = std::uniform_int_distribution<T>;
};
template <typename T>
struct distribution_traits<
T, typename std::enable_if<std::is_floating_point<T>::value,
std::uniform_real_distribution<T> >::type > {
using type = std::uniform_real_distribution<T>;
};
而且Clang抱怨
dist_traits.cpp:28:3: error: implicit instantiation of undefined template 'distribution_traits<float, void>'
distribution_traits<float>::type int_dist;
^
无论哪种方式都无法通过MSVC ++ 12.0编译,并且错误消息类似。
有谁能解释我在SFINAE做错了什么?谢谢!
对于那些对解决方案感到好奇的人,这是编译的那个:
template <typename T>
auto dist() -> typename std::enable_if<std::is_integral<T>::value, std::uniform_int_distribution<T>>::type;
template <typename T>
auto dist() -> typename std::enable_if<std::is_floating_point<T>::value, std::uniform_real_distribution<T>>::type;
template <typename T>
struct distribution_traits {
using type = decltype(dist<T>());
};
BTW,如果将dist
函数放入distribution_traits
,则编译将失败并出现错误:函数仅在返回类型方面不同,不能重载。 :(
答案 0 :(得分:1)
SFINAE可用于在替换模板参数时丢弃函数模板和类模板特化的重载。
它不能像您尝试的那样与类型/模板别名一起使用。
关于您的工作代码 - 将dist
放入类中是行不通的,因为您尝试在没有对象的情况下在dist
内调用decltype
。将dist
设为静态,它将起作用:
template <typename T>
struct distribution_traits {
template <typename U>
static auto dist() -> typename std::enable_if<std::is_integral<U>::value, std::uniform_int_distribution<U>>::type;
template <typename U>
static auto dist() -> typename std::enable_if<std::is_floating_point<U>::value, std::uniform_real_distribution<U>>::type;
using type = decltype(dist<T>());
};
要使实现2起作用,您需要省略enable_if
的第二个参数:
模板 struct distribution_traits;
template <typename T>
struct distribution_traits<
T, typename std::enable_if<std::is_integral<T>::value>::type> {
using type = std::uniform_int_distribution<T>;
};
否则您定义的专业化为distribution_traits<T, uniform_int_distribution<T>>
且与distribution_traits<float>
之类的实例化不匹配,因为第二个参数默认为void
。