1

テンプレートがあります:

template<typename... Ts> //T1,T2,T3,...
struct foo {
  //my struct
};

static_assertT1、T3、T5、... (「奇数型」) と T2、T4、T6、... (「偶数型」) を別々にチェックしたい。

私はこの簡単な解決策を見つけました:

template<size_t N, typename... Ts>
struct perform_checks {};

template<size_t N, typename T, typename U, typename... Ts>
struct perform_checks<N, T, U, Ts...> : perform_checks<N, Ts...>
{
  //check for odd types
  static_assert(std::is_default_constructible<T>::value,"failure");

  //check for even types
  static_assert(std::is_copy_constructible<U>::value,"failure");
};

このNパラメーターにより、終了できます。私はこのように使用します:

template<typename... Ts>
struct foo {
  perform_checks<0,Ts...> hello;
};

これはうまく機能しているようです。helloしかし、変数を回避することは可能ですか? それ以外の目的で使用することはありません。

4

3 に答える 3

2

enable_if1 (および boost::mpl) は、多かれ少なかれ次の方法で使用できます。

#include <boost/mpl/and.hpp>
template<size_t N, typename... Ts>
struct perform_checks {};

template<size_t N, typename T, typename U, typename... Ts>
struct perform_checks<N, T, U, Ts...> : perform_checks<N, Ts...>
{
    typedef boost::mpl::and_<std::is_default_constructible<T>::type, 
        std::is_copy_constructible<U>::type> type;
};

template < class... Ts,
       class = typename std::enable_if<perform_checks<0, Ts...>::type>
struct foo {
  //my struct
};
于 2013-06-27T22:41:40.423 に答える
2

個人的にfoo派生:perform_checks<>

template <typename... Ts> struct foo : private perform_checks<Ts...> {
 // stuff
};

Nああ、必要のないパラメーターを取り除きます。

template <typename... Ts> struct perform_checks {};
template <typename T> struct perform_checks<T> {
  template <typename U> struct dependent_name_hack : std::false_type {};
  static_assert(dependent_name_hack<T>::value,
                "Odd number of parameters not acceptable.");
};
template <typename T, typename U, typename... Ts>
struct perform_checks<T, U, Ts...> : perform_checks<Ts...> {
  //check for odd types
  static_assert(std::is_default_constructible<T>::value,"failure");

  //check for even types
  static_assert(std::is_copy_constructible<U>::value,"failure");
};
于 2013-06-27T22:38:33.720 に答える
2

fooOPの唯一の目的は、インスタンス化されたときにチェックをトリガーすることです。そのため、変数が必要ですhello。これは、のインスタンス化ですfoo

私はむしろ の特性のアプローチに従いたいと思い<type_traits>ます。より正確には、指定された型がテストに合格するかどうかに応じて、orと呼ばれるpublicメンバーperform_checksを持つclass(or ) になります。次に、 false の場合はシングルを使用してコンパイルを停止します。structstatic constexpt boolvaluetruefalsestatic_assertvalue

テンプレート型引数の数が偶数であると仮定する私の解決策は次のとおりです。

#include <type_traits>

template<typename First, typename Second, typename... Others>
struct perform_checks :
    std::integral_constant<bool,
        perform_checks<First, Second>::value && // Checks First and Second
        perform_checks<Others...>::value        // Recursively "calls" itself on Others
    > {
};

// This specialization finishes the recursion and effectively performs the test
template<typename First, typename Second>
struct perform_checks<First, Second> :
    std::integral_constant<bool,
        std::is_default_constructible<First>::value && // Checks First
        std::is_copy_constructible<Second>::value      // Checks Second
    > {
};

簡単なテストを次に示します。

struct NonDefaultConstructible {
    NonDefaultConstructible() = delete;
};

struct NonCopyConstructible {
    NonCopyConstructible(const NonCopyConstructible&) = delete;
};

int main() {
    static_assert(perform_checks<int, double>::value, "Failure");
    static_assert(perform_checks<int, int, double, double>::value, "Failure");
    static_assert(!perform_checks<NonDefaultConstructible, int>::value, "Failure");
    static_assert(!perform_checks<int, NonCopyConstructible>::value, "Failure");
    static_assert(!perform_checks<int, int, double, NonCopyConstructible>::value, "Failure");
}

変数が作成されていないことに注意してください。

于 2013-06-28T09:30:14.527 に答える