cpp 日常


hana


hana1


所以foobar是不是常量表达式呢???

  • 如果是,为啥没加constexpr???
  • 如果不是, 为啥能进行静态断言???

再来看
hana2

是不是更方了???? what the hell !!!


接下来,再来看

$ cat x.cc && gg x.cc                                                                                                                                                                    1 ↵
template<typename T> struct Test { T t; };

template<typename T, typename U>
constexpr bool operator== (const Test<T>&, const Test<U>&)
{
  return false;
}

template<typename T>
constexpr bool operator== (const Test<T>& lhs, const Test<T>& rhs)
{
  return lhs.t == rhs.t;
}

template<typename T> constexpr auto make_test(const T& t)
{
  return Test<T>{t};
}

int main()
{
  struct Foo {};
  struct Bar{};

  auto foo = make_test(Foo{});
  auto bar = make_test(Bar{});
  static_assert(foo == bar);

  constexpr auto one = make_test(1);
  constexpr auto two = make_test(2);
  static_assert(one == two);
}
x.cc: In function ‘int main()’:
x.cc:32:3: error: static assertion failed
   static_assert(foo == bar);
   ^~~~~~~~~~~~~
x.cc:36:3: error: static assertion failed
   static_assert(one == two);
   ^~~~~~~~~~~~~

很明显,operator==都是constexpr修饰的函数,区别在于,当比较的两者类型不同时直接返回false,这是完全正确的! 当类型相同时,才真正的进行比较,而这个比较需要对象已经构建出来,如果变量不用constexpr修饰,在编译期就无法利用成员变量进行比较。

所以, 上面两个问题的回答如下:

  • foobar不是常量表达式,你可以检查它们是否为const来确定
  • 因为foo == bar这个表达式使用的重载是constexpr function,并且这个函数只使用了类型,同时类型是可以在编译期确定的

PS. Boost.Hana在比较时还做了其他的一些工作,比如判断两个类型是否可以相互转换。


随便,写一个超级简单的编译期分支

#include <functional>

namespace nm
{
  template<typename> struct IF;
  template<> struct IF<std::integral_constant<bool, true>>
  {
    template<typename T, typename F>
    constexpr static T apply(T&& t, F&&) { return std::forward<T>(t); }
  };
  template<> struct IF<std::integral_constant<bool, false>>
  {
    template<typename T, typename F>
    constexpr static  F apply(T&&, F&& f) { return std::forward<F>(f); }
  };

  template<typename C, typename T, typename F> constexpr auto if_(C&&, T&& t, F&& f)
  {
    using R = typename std::remove_reference<C>::type;
    return IF<typename R::type>::apply(t, f);
  }

  constexpr auto true_c = std::integral_constant<bool, true>{};
  constexpr auto false_c = std::integral_constant<bool, false>{};
}

#include <boost/hana.hpp>
namespace hana = boost::hana;

int main()
{
  {
    using nm::if_;
    auto x = if_(std::is_convertible<const char[4], const char*>{}, "233", 233);
    auto y = if_(nm::false_c, "233", 223);
    static_assert(std::is_same_v<decltype(x), const char*>);
    static_assert(std::is_same_v<decltype(y), int>);
    // auto z = if_(false, "233", 223); // error
  }
  {
    using hana::if_;
    auto x = if_(std::is_convertible<const char[4], const char*>{}, "233", 233);
    auto y = if_(hana::false_c, "233", 233);
    static_assert(std::is_same_v<decltype(x), const char*>);
    static_assert(std::is_same_v<decltype(y), int>);
    // auto z = if_(false, "233", 223); // error
  }
}


转载请注明:Serenity » cpp 日常

上一篇

下一篇