c++ - Traits 类作为模板模板参数

标签 c++ templates c++14 template-meta-programming traits

我的代码中散布着特征类,它们遵循相同的基本习惯用法:

template<class Frame, typename = void>
struct frame_traits
{
    typedef void base_frame_type;
};

template<class Frame>
struct frame_traits<Frame, typename std::void_t<
    typename Frame::base_frame_type>::type>
{
    typedef typename Frame::base_frame_type         base_frame_type;
};

我有一堆使用它们的特征检查器,它们也遵循类似的习惯用法:

template <typename T>
struct has_base_frame_type : std::integral_constant<bool,
    !std::is_same<typename frame_traits<T>::base_frame_type, void>::value>::type {};

然而,事实证明 has_base_frame_type 对我的代码中的多个概念变得有用,我想进一步概括它,以便我可以将特征类作为附加参数传递:

template <typename T, template<typename> class Traits = frame_traits>
struct has_base_frame_type : std::integral_constant<bool,
    !std::is_same<typename Traits<T>::base_frame_type, void>::value>::type {};

但这不起作用,因为 templates with default arguments cannot be used as template template parameters .

我知道如果我总是在模板实例化中使用特征类(并修改特征检查器以接受它),我可以解决这个问题,即

has_base_frame_type<frame_traits<MyClass>>::value

但我不想这样做,因为它会是 all too easy忘记并通过非特质类(class)。事实上,我最初就是这样编写代码的,直到我多次忘记了这一特征并重构了它。

有什么办法可以修改我的特征类习惯用法来解决模板模板参数问题吗?

最佳答案

框架:

#include <type_traits>

template <typename...>
using void_t = void;

template <typename AlwaysVoid, template <typename...> class Operation, typename... Args>
struct detect_impl : std::false_type {};

template <template <typename...> class Operation, typename... Args>
struct detect_impl<void_t<Operation<Args...>>, Operation, Args...> : std::true_type {};

template <template <typename...> class Operation, typename... Args>
using detect = detect_impl<void, Operation, Args...>;

探测器:

template <class Frame>
using frame_traits = typename Frame::base_frame_type;

template <class Frame>
using other_frame_traits = typename Frame::other_frame_type;

使用默认检测器的特征:

template <typename T, template <typename...> class Traits = frame_traits>
using has_frame_type = detect<Traits, T>;

测试:

struct A
{
    using base_frame_type = void;
};

struct B
{
    using other_frame_type = void;
};

int main()
{
    static_assert(has_frame_type<A>{}, "!");  // default
    static_assert(!has_frame_type<B>{}, "!"); // default

    static_assert(!has_frame_type<A, other_frame_traits>{}, "!"); // non-default
    static_assert(has_frame_type<B, other_frame_traits>{}, "!");  // non-default
}

DEMO

关于c++ - Traits 类作为模板模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36746410/

相关文章:

c++ - 行更改的文件输入c++

c++ - c++ 中基于范围的 for 循环的替代方法

c++ - 标准是否保证了 lambda 的可继承性?

c++ Overload operator bool() 使用 operator+ 给出模糊的重载错误

c++ - 包扩展不在最后一个参数中的可变参数函数模板

c++ - 在完全专用的类模板中初始化静态成员

没有模板函数继承的 C++ 接口(interface)

c++ - `std::exchange` 不是 `constexpr` 有什么原因吗?

c++ - 为什么在c++14中定义了shared_timed_mutex,而在c++17中定义了shared_mutex?

c++ - Variadic 模板错误 -- MSVS2013 编译,clang-3.5 不编译