0

Consider the following code:

#include <string>
#include <iostream>

#include <memory>
#include <utility>

#include <vector>
#include <array>
#include <tuple>
#include <variant>

#include <algorithm>
#include <numeric>


#include <type_traits>
#include <functional>
#include <stdexcept>

// a few global things that will be needed by Heap and friends
// credit https://stackoverflow.com/questions/34099597/check-if-a-type-is-passed-in-variadic-template-parameter-pack
template<typename T, typename... Ts>
constexpr bool contained_in = std::disjunction_v<std::is_same<T, Ts>...>;

// credit https://stackoverflow.com/questions/18986560/check-variadic-templates-parameters-for-uniqueness
template <typename T> 
struct Base {};

template <typename... Ts>
struct Types : Base<Ts>...
{
  template <typename T>
  constexpr auto operator+(Base<T>)
  {
    if constexpr (std::is_base_of_v<Base<T>, Types>)
      return Types{};
    else
      return Types<Ts..., T>{};
  }

  constexpr size_t size() const
  {
    return sizeof...(Ts);
  }
};

template <typename... Ts>
constexpr bool unique_types = ( (Types<>{} + ... + Base<Ts>{}).size() == sizeof...(Ts) );

// credit https://stackoverflow.com/questions/42580997/check-if-one-set-of-types-is-a-subset-of-the-other/
template <typename T, typename U>
constexpr bool is_subset_of = false;

template <template <typename, typename...> typename T, typename ...Ts, template <typename, typename...> typename U, typename ...Us>
constexpr bool is_subset_of<T<Ts...>, U<Us...>> 
= (contained_in<Ts, Us...> and ...);

template <typename T, typename U>
constexpr bool mutual_overlap = false;

template <template <typename, typename...> typename T, typename ...Ts, template <typename, typename...> typename U, typename ...Us>
constexpr bool mutual_overlap<T<Ts...>, U<Us...>> 
= (is_subset_of<T<Ts...>, U<Us...>> or is_subset_of<U<Us...>, T<Ts...>>);

template <typename ...Ts>
  class Collection {
};

int main() {
  // check for the helper functions
  std::cout << "iso ci cif " << is_subset_of<Collection<float>, Collection<int, float>> << std::endl;
  std::cout << "iso cif ci " << is_subset_of<Collection<int, float>, Collection<int>> << std::endl;
  std::cout << "iso cif cif " << is_subset_of<Collection<int, float>, Collection<int, float>> << std::endl;
  std::cout << "iso cif cfi " << is_subset_of<Collection<int, float>, Collection<float, int>> << std::endl;
  std::cout << "iso cic cif " << is_subset_of<Collection<int, char>, Collection<int, float>> << std::endl;
  std::cout << "iso ccf cud " << is_subset_of<Collection<char, float>, Collection<uint, double>> << std::endl;
  std::cout << "iso ccf ccfid " << is_subset_of<Collection<char, float>, Collection<char, float, int, double>> << std::endl;
  std::cout << "iso ccfu ccfid " << is_subset_of<Collection<char, float, uint>, Collection<char, float, int, double>> << std::endl;

  std::cout << "mo ci cif " << mutual_overlap<Collection<float>, Collection<int, float>> << std::endl;
  std::cout << "mo cif ci " << mutual_overlap<Collection<int, float>, Collection<int>> << std::endl;
  std::cout << "mo cif cif " << mutual_overlap<Collection<int, float>, Collection<int, float>> << std::endl;
  std::cout << "mo cif cfi " << mutual_overlap<Collection<int, float>, Collection<float, int>> << std::endl;
  std::cout << "mo cic cif " << mutual_overlap<Collection<int, char>, Collection<int, float>> << std::endl;
  std::cout << "mo ccf cud " << mutual_overlap<Collection<char, float>, Collection<uint, double>> << std::endl;
  std::cout << "mo ccf ccfid " << mutual_overlap<Collection<char, float>, Collection<char, float, int, double>> << std::endl;
  std::cout << "mo ccfu ccfid " << mutual_overlap<Collection<char, float, uint>, Collection<char, float, int, double>> << std::endl;

  return 0;
}

demo

(the headers are not all strictly necessary and is copypasted off a project)

Testing the results with GCC and clang, they give different results. I'm thinking GCC is correct here, from the fact that the results are as intended, but why does clang mark all of these false?

Both are compiled with the trunk version.

cigien
  • 57,834
  • 11
  • 73
  • 112
afiqaize
  • 1
  • 1
  • 2
    Please try to make your questions *self-contained*, which means we should not need to go to external resource to figure out the whole question (for example please put the [mcve] inside the question itself). This is crucial since external links can change their contents, or disappear completely, making the question useless. Remember that this site isn't only to help only you right now, but also future people having the same or similar problems in the future. – Some programmer dude Jul 18 '20 at 20:00
  • 1
    Works in Clang if you build with `-frelaxed-template-template-args`. Rule of thumb: if templates misbehave in Clang, try this flag. – HolyBlackCat Jul 18 '20 at 20:06
  • My bad about linking rather than pasting. +1 for the clang flag, didn't know about it. – afiqaize Jul 18 '20 at 21:25

0 Answers0