2

したがって、次のケースがあります。長い例で申し訳ありませんが、正しくコンパイルする必要があります。

#include <tuple>
#include <functional>
#include <iostream>

#include <boost/mpl/fold.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/vector.hpp>


namespace mpl = boost::mpl;

namespace aux
{
template <typename ...Args>
struct to_vector
{ };

template <typename T, typename ...Args>
struct to_vector<T, Args...>
{ typedef typename mpl::push_front<typename to_vector<Args...>::type, T>::type type; };

template <typename T>
struct to_vector<T>
{ typedef typename mpl::vector<T> type; };

template <>
struct to_vector<>
{ typedef typename mpl::vector<> type; };

template <typename Dest, typename T>
struct tuple_adder
{
  typedef decltype(std::tuple_cat(std::declval<Dest>(), std::make_tuple(std::declval<T>()))) type;
};

}

struct foo
{
  struct storage
  { };

  template <typename T>
  struct placeholder : storage
  {
    placeholder(T&& t) : content(t)
    { }

    T content;
  };

  storage* data;


  template <typename ...Args>
  foo(Args&&... args)
  : data()
  {
    typedef typename mpl::fold<
      typename aux::to_vector<Args...>::type,
      std::tuple<>,
      aux::tuple_adder<mpl::_1, mpl::_2>
    >::type tuple_type;
    // Instantiate the tuple
    data = new placeholder<tuple_type>(std::make_tuple(std::forward<Args>(args)...));
  }

  template <typename ...Args>
  void set(Args&&... args)
  {
    typedef typename mpl::fold<
      typename aux::to_vector<Args...>::type,
      std::tuple<>,
      aux::tuple_adder<mpl::_1, mpl::_2>
    >::type tuple_type;

    auto tp = static_cast<placeholder<tuple_type>*>(data);
    *tp = std::make_tuple(std::forward<Args>(args)...);
  }
};


int main()
{
  foo f(1, 2., std::string("Hello"));

  f.set(4, 3., std::string("Bar"));

  f.set(3., std::string("Bar"), 3.);
}

アイデアは単純で、foo型消去を利用しtupleて、コンストラクターを介して構築された a を格納します。次に、可変引数リストから生成されたものが保持されているタプルと一致するset場合にのみ許可されるという制限が必要です(残念ながら、型が消去されています)。tuple

を使用して実行時にこれを検出できるtypeid()ようになりましたが、コンパイル時に同じ検出を行う方法があるかどうかを知りたいです。唯一の制約はfooテンプレート化できないことであり、必要に応じてフィールドを使用して構築variantできるようにしたいのでアウトですfoo(すべてコンパイル時に指定されます...)

答えは、これは不可能であるということです(型消去のため)が、この機能を実現する方法のいくつかのアイデアを望んでいます...

4

1 に答える 1

3

コンパイル時の型システムのポイントは、型の値に対して許容される操作を制限することです。2 つのオブジェクトが同じタイプの場合、それらは同じ許容操作を許可します。

いいえ、違いを消去したことを考えると、コンパイラが許可したいものを知る方法はありません。

于 2013-03-01T12:00:04.680 に答える