避免在此模板代码中创建变量

时间:2013-06-27 22:23:45

标签: c++ templates c++11

我有一个模板:

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

我想分别对T1,T3,T5,......(“奇数类型”)以及T2,T4,T6,......(“偶数类型”)进行static_assert检查。

我找到了这个简单的解决方案:

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变量吗?我从不将它用于任何其他目的。

3 个答案:

答案 0 :(得分: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");
};

答案 1 :(得分:2)

您可以通过以下方式使用enable_if 1(和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
};

答案 2 :(得分:2)

OP中foo的唯一目的是在实例化时触发检查。这就是你需要变量hello的原因:它是foo的实例化。

我宁愿在<type_traits>中遵循特征的方法。更确切地说,我会将perform_checks变为class(或struct),其成员static constexpt bool value成员true或{false 1}}取决于给定类型是否通过测试。然后,如果static_assert为假,我会使用单个value来停止编译。

我的解决方案假设模板类型参数的数量是偶数,如下:

#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");
}

请注意,未创建任何变量。