Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
339 views
in Technique[技术] by (71.8m points)

c++11 - C++ how to generate all the permutations of function overloads?

Lets say I have classes Date and classes Year, Month and Day.

struct Date {
  Date(Year year, Month month, Day day) : d(day), m(month), y(year) {};
  Date(Month month, Day day, Year year) : d(day), m(month), y(year) {};
  Date(Day day, Month month, Year year) : d(day), m(month), y(year) {};
  Date(Day day, Year year, Month month) : d(day), m(month), y(year) {};
  ...
  ...

  private:
    Day d;
    Month m;
    Year y;
}

This allows me not to have a specific layout of arguments for Date as I have a lot of overloadings.

Am I able to generate all the permutations/overloadings automatically?

Just to be clear:

  • Permutations are only of argument layout, nothing about them should change as I know that would not be possible to automate.
  • All the generated overloadings should have the same code as only the layout of arguments changes not the logic itself.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

With C++14, you may do:

struct Date {
public:
    Date(const Year& year, const Month& month, const Day& day) :
        d(day), m(month), y(year)
    {}

    template <typename T1, typename T2, typename T3>
    Date(const T1& t1, const T2& t2, const T3& t3) : 
        Date(std::get<Year>(std::tie(t1, t2, t3)),
             std::get<Month>(std::tie(t1, t2, t3)),
             std::get<Day>(std::tie(t1, t2, t3)))
    {}

private:
    Day d;
    Month m;
    Year y;
};

Edit: if you would also allow default argument, you may do something like:

namespace detail
{
    template <typename T, typename... Ts> struct has_T;

    template <typename T> struct has_T<T> : std::false_type {};

    template <typename T, typename... Ts> struct has_T<T, T, Ts...>
    : std::true_type {};

    template <typename T, typename Tail, typename... Ts>
    struct has_T<T, Tail, Ts...> : has_T<T, Ts...> {};

    template <typename T, typename... Ts>
    const T& get_or_default_impl(std::true_type,
                                 const std::tuple<Ts...>& t,
                                 const T&)
    {
        return std::get<T>(t);
    }

    template <typename T, typename... Ts>
    const T& get_or_default_impl(std::false_type,
                                 const std::tuple<Ts...>&,
                                 const T& default_value)
    {
        return default_value;
    }

    template <typename T1, typename T2> struct is_included;

    template <typename... Ts>
    struct is_included<std::tuple<>, std::tuple<Ts...>> : std::true_type {};

    template <typename T, typename... Ts, typename ... Ts2>
    struct is_included<std::tuple<T, Ts...>, std::tuple<Ts2...>> :
        std::conditional_t<has_T<T, Ts2...>::value,
                          is_included<std::tuple<Ts...>, std::tuple<Ts2...>>,
                          std::false_type> {};

}

template <typename T, typename... Ts>
const T& get_or_default(const std::tuple<Ts...>& t,
                        const T& default_value = T{})
{
    return detail::get_or_default_impl<T>(detail::has_T<T, Ts...>{}, t, default_value);
}

And then

struct Date {
public:
    Date(const Year& year, const Month& month, const Day& day) :
        d(day), m(month), y(year)
    {}

    template <typename ... Ts,
              typename std::enable_if_t<
                  detail::is_included<std::tuple<Ts...>,
                  std::tuple<Year, Month, Day>>::value>* = nullptr>
    Date(const Ts&... ts) :
        Date(get_or_default<const Year&>(std::tie(ts...)),
             get_or_default<const Month&>(std::tie(ts...)),
             get_or_default<const Day&>(std::tie(ts...)))
    {}

private:
    Day d;
    Month m;
    Year y;
};

Live Demo
Live Demo with invalid constructor call


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...