3

Скажем, у меня есть Filter metafunction, который фильтрует список типов:Создать «свести на нет» обертка для класса type_traits

template<template<typename> class TFilter, typename... Ts> 
using Filter = MetaList</* check TFilter<T>{}() for every type in Ts... */>; 

metafunction может быть использован, как это:

Filter<std::is_pod, int, char, std::string, int> 
// ...returns... 
MetaList<int, char, int> 

сейчас , Я хотел бы получить все типы, которые не являются POD. Я мог бы создать метафайл FilterNot, но мне действительно нужно «отрицание» и в других метафайлах.

Можно ли создать обертку отрицания для любого типа типа-like template class?

Желаемый код:

Filter<Negate<std::is_pod>, int, char, std::string, int> 
// ...returns... 
MetaList<std::string> 

ответ

3
template<template<class...>class Z> 
struct negate { 
    template<class...Ts> 
    using result=std::integral_constant<bool, !Z<Ts...>::value>; 
}; 
Filter<negate<std::is_pod>:: template result, int, char, std::string, int>; 

или

Filter<typename negate<std::is_pod>::result, int, char, std::string, int>; 

в зависимости от компилятора должен работать. (IIRC, некоторые компиляторы изворотливы об этом)

Как я нахожу этот синтаксис неудобным, может быть, взять список тестов на цепочку? Тогда отрицанием это просто еще одна черта в стеке:

template<template<class...>class... Zs> 
struct tests {}; 

затем принять tests и применить Zs рекурсивно.

template<class B> 
using negate=std::integral_constant<bool,!B::value>; 

filters<tests<negate, std::is_pod>, int, std::string> 

Еще один подход заключается в тесты и сделать их constexpr функции на tag<type>{} (это легко сделать), которые являются синтаксически легче составить. Переход от template<class>class до constexpr bool(tag<class>) - это не сложно.

+0

Вы можете написать 'Z {}' 'вместо Z :: value' (см комментарий к вопросу:!'/* Проверить TFilter {}() для каждого типа в Ts ... */'). – Constructor

+0

@constructor согласился, но решил, что требование поддержки 'constexpr' не стоит (первая версия использовала этот точный синтаксис). – Yakk

+0

Ах, 'constexpr' ... Его поддержка подобна тому, что вы спотыкаетесь снова и снова. – Constructor

2

Один из способов сделать это:

#include <iostream> 
#include <type_traits> 
using namespace std; 

template<template <class> class P> 
struct invert 
{ 
    template<class... Args> 
    struct templ { 
    static constexpr bool value = ! P<Args...>::value; 
    }; 
}; 



int main() 
{ 
    cout << invert<is_pod>::templ<string>::value << endl; 
    cout << is_pod<string>::value << endl; 

    return 0; 
}