12

関数アプリケーションがコンパイラによって拒否されることを表明したいというアプリケーションの問題があります。SFINAEでこれを確認する方法はありますか?

std::transformたとえば、あるconst範囲が違法であることを検証したいとします。これが私がこれまでに持っているものです:

#include <algorithm>
#include <functional>
#include <iostream>

namespace ns
{

using std::transform;

template<typename Iterator1, typename Iterator2, typename UnaryFunction>
  struct valid_transform
{
  static Iterator1 first1, last1;
  static Iterator2 first2;
  static UnaryFunction f;

  typedef Iterator2                   yes_type;
  typedef struct {yes_type array[2];} no_type;

  static no_type transform(...);

  static bool const value = sizeof(transform(first1, last1, first2, f)) == sizeof(yes_type);
};

}

int main()
{
  typedef int *iter1;
  typedef const int *iter2;
  typedef std::negate<int> func;

  std::cout << "valid transform compiles: " << ns::valid_transform<iter1,iter1,func>::value << std::endl;

  std::cout << "invalid transform compiles: " << ns::valid_transform<iter1,iter2,func>::value << std::endl;

  return 0;
}

残念ながら、私の特性は合法と違法の両方の事件を拒否します。結果:

$ g++ valid_transform.cpp 
$ ./a.out 
valid transform compiles: 0
invalid transform compiles: 0
4

2 に答える 2

4

あなたの質問はSFINAE+sizeof=式がコンパイルされるかどうかを検出するのに似ています。

その答えの要約sizeof:関数テンプレートのインスタンス化を含め、渡された式の型を評価しますが、関数呼び出しは生成しません。sizeof(std::transform(iter1(), iter1(), iter2(), func()))これが、コンパイルされない場合でもコンパイルさ れるLol4t0の観測の背後にある理由std::transform(iter1(), iter1(), iter2(), func())です。

具体的な問題は、に提供される出力範囲についてLol4t0の回答からテンプレートを評価することで解決できますstd::transform。ただし、関数呼び出しがコンパイルされることをテンプレートで検証するという一般的な問題は、このsizeof + SFINAEトリックでは解決できないようです。(実行時の関数呼び出しから導出できるコンパイル時の式が必要になります)。

ConceptGCCを試して、必要なコンパイル時チェックをより便利な方法で表現できるかどうかを確認することをお勧めします。

于 2012-05-05T09:20:47.137 に答える
3

私の答えでは、問題、イテレータ定数が与えられているかどうかを判断する方法に焦点を当てたいと思います: std::is_constが言及されましたが、この場合は機能しません(gcc4.7)。

私はそれが次のように実装されていると思います

template <typename T>
struct is_const
{
    enum {value = false };
};

template <typename T>
struct is_const<const T>
{
    enum {value = true };

};

さて、この構造体で参照型をチェックすることはできません。それらは特殊化と一致しません。なぜなら、const T一致するint& const、つまりintへの定数参照であり、定数intへの参照const int&ではなく、最初は意味がないからです。

わかりましたが、イテレータが次の構造体で一定であるかどうかを判断できます。

template <typename Iterator>
struct is_iterator_constant
{
    typedef char yes_type;
    typedef struct{ char _[2];}  no_type;
    template <typename T>
    static no_type test(T&);

    template <typename T>
    static yes_type test(...);

    enum {value = sizeof(test<typename std::iterator_traits<Iterator>::value_type>(*Iterator())) == sizeof(yes_type) };

};
于 2012-05-05T18:12:53.900 に答える