В C ++, вы можете сравнить шаблоны так же, как вы можете сравнивать типы? - PullRequest
0 голосов
/ 14 января 2019

У меня была идея для шаблона сравнения, аналогичного std::is_same. Если два шаблона одинаковы, то по крайней мере их экземпляры с заданными аргументами шаблона будут одинаковыми.

template<template<class...> class LHS, template<class..> class RHS, class... S>
using is_same_template = std::is_same<LHS<S...>, RHS<S...>>::value;

Есть ли способ сравнить LHS и RHS без S...? Я считаю, что без S... компаратор в любом случае пришлось бы создавать более чем S.... Если бы они были шаблонными функциями, я бы не ожидал, что смогу их сравнить, мне нужно сравнить их экземпляры. Правильна ли моя интуиция?

Ответы [ 2 ]

0 голосов
/ 14 января 2019

У меня была идея для компаратора шаблона, аналогичного std :: is_same. [...] Есть ли способ сравнить LHS и RHS без S...?

Вы можете черпать вдохновение из "возможной реализации" std::is_same на этой странице и написать аналог для шаблона-шаблона

template <template <typename ...> class, template <typename ...> class>
struct is_tpl_same : public std::false_type
 { };

template <template <typename ...> class C>
struct is_tpl_same<C, C> : public std::true_type
 { };

Вы можете проверить, что

static_assert( true  == is_tpl_same<std::set, std::set>::value, "!" );
static_assert( false == is_tpl_same<std::vector, std::set>::value, "!" );
0 голосов
/ 14 января 2019

Похоже, что тот же подход, который вы можете использовать с типами или значениями, работает для шаблонов. Первые две строки показывают использование только с шаблонами и не требуют функций equals или tag или каких-либо аргументов для предоставленных шаблонов. Вторые два извлекают шаблоны из значений и выполняют те же тесты для них.

#include <iostream>

template<class...> struct A {};
template<class...> struct B {};

template<template<class...> class S>
struct Tag;

template<template<class...> class S>
struct Tag {
    template<template<class...> class T>
    constexpr auto equals(Tag<T>) -> std::false_type { return {}; }
    constexpr auto equals(Tag<S>) -> std::true_type { return {}; }
};

template<template<class...> class T, class... V>
Tag<T> tag(T<V...> const&) { return {}; }

template<class S, class T>
auto equals(S && s, T && t) -> decltype(tag(s).equals(tag(t))) { return {}; }

int main(int argc, const char *argv[]) {
    using namespace std;

    cout << Tag<A>{}.equals(Tag<A>{}) << "; " << Tag<A>{}.equals(Tag<B>{}) << endl;
    // 1; 0
    cout << Tag<B>{}.equals(Tag<A>{}) << "; " << Tag<B>{}.equals(Tag<B>{}) << endl;
    // 0; 1

    A<float> af;
    A<double> ad;
    B<int> bi;
    B<char, char> bcs;

    cout << equals(af, ad) << "; " << equals(af, bi) << endl;
    // 1; 0
    cout << equals(bi, ad) << "; " << equals(bi, bcs) << endl;
    // 0; 1

}
...