繁体   English   中英

可变参数模板中的类成员函数

[英]Class member function in variadic template

我正在尝试编写一个可变函数来生成一个gmock匹配器,它可以立即检查多个属性的零关系。

// Class with three properties.
class Vec3 {
 public:
  double x() const;
  double y() const;
  double z() const;
};

using ::testing::AllOf;
using ::testing::Property;

Vec3 vec3;
// I could do this...
EXPECT_THAT(vec3, AllOf(Property(&Vec3::x, Eq(0.0)),
    Property(&Vec3::y, Eq(0.0)), Property(&Vec3::z, Eq(0.0)));

// But I'd want to do something like this...
EXPECT_THAT(vec3, PropertiesAreZero(&Vec3::x, &Vec3::y, &Vec3::z));

我似乎无法在编写生成等效匹配器的变量函数方面取得进展。 这是我一直在尝试的:

template <typename T, typename M, typename P>
Matcher<T> PropertiesAre(M matcher, P(T::*... args)()) {
    return AllOf(Property(args, matcher)...);
};

template <typename T, typename... Others>
Matcher<T> PropertiesAreZero(Others... others) {
    return PropertiesAre(Eq(0.0), others...);
}

Vec3 vec3;
EXPECT_THAT(vec3, PropertiesAreZero(&Vec3::x, &Vec3::y, &Vec3::z));

我收到以下编译错误:

error: type 'P (T::*)()' of function parameter pack does not contain any unexpanded parameter packs
Matcher<T> PropertiesAre(M matcher, P(T::*... args)()) {
                                    ~~~~~~^~~~~~~~~~~
error: pack expansion does not contain any unexpanded parameter packs
  return AllOf(Property(args, matcher)...);
               ~~~~~~~~~~~~~~~~~~~~~~~^
error: no matching function for call to 'PropertiesAre'
          PropertiesAre(Ne(0.0),
          ^~~~~~~~~~~~~
gmock/include/gmock/gmock-matchers.h:5240:60: note: expanded from macro 'EXPECT_THAT'
    ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
                                                           ^~~~~~~
gtest/include/gtest/gtest_pred_impl.h:117:23: note: expanded from macro 'EXPECT_PRED_FORMAT1'
  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
                      ^~~~~~~~~~~
gtest/include/gtest/gtest_pred_impl.h:104:17: note: expanded from macro 'GTEST_PRED_FORMAT1_'
  GTEST_ASSERT_(pred_format(#v1, v1), \
                ^~~~~~~~~~~
gtest/include/gtest/gtest_pred_impl.h:80:52: note: expanded from macro 'GTEST_ASSERT_'
  if (const ::testing::AssertionResult gtest_ar = (expression)) \
                                                   ^~~~~~~~~~
note: candidate function template not viable: requires 2 arguments, but 4 were provided
Matcher<T> PropertiesAre(M matcher, P(T::*... args)()) {
           ^
error: no matching function for call to 'PropertiesAreZero'
          PropertiesAreZero(
          ^~~~~~~~~~~~~~~~~
gmock/include/gmock/gmock-matchers.h:5240:60: note: expanded from macro 'EXPECT_THAT'
    ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
                                                           ^~~~~~~
gtest/include/gtest/gtest_pred_impl.h:117:23: note: expanded from macro 'EXPECT_PRED_FORMAT1'
  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
                      ^~~~~~~~~~~
gtest/include/gtest/gtest_pred_impl.h:104:17: note: expanded from macro 'GTEST_PRED_FORMAT1_'
  GTEST_ASSERT_(pred_format(#v1, v1), \
                ^~~~~~~~~~~
gtest/include/gtest/gtest_pred_impl.h:80:52: note: expanded from macro 'GTEST_ASSERT_'
  if (const ::testing::AssertionResult gtest_ar = (expression)) \
                                                   ^~~~~~~~~~
note: candidate template ignored: couldn't infer template argument 'T'
Matcher<T> PropertiesAreZero(Others... others) {
           ^
error: no matching function for call to 'PropertiesAreZero'
              PropertiesAreZero(
              ^~~~~~~~~~~~~~~~~

我真的很感激我能得到任何帮助。 我现在已经反对这一整天了。

如果没有像AllOf那样的定义,那么完全正确地解决这个问题有点棘手,但这是我对你的目标的准备,然后我会试着解释你的错误。

template<typename R, typename T>
using const_member_ptr = R(T::*)() const;

template<typename T, typename M, typename... R>
Matcher<T> PropertiesAre(M matcher, const_member_ptr<R,T> ...args)
{
    return AllOf<T>(Property(args, matcher)...);
}

template <typename T, typename... R>
Matcher<T> PropertiesAreZero(const_member_ptr<R,T>... others)
{
    return PropertiesAre<T>(Eq(0.0), others...);
}

第一个问题是在您的PropertiesAreZero版本中,编译器无法推断出T是什么。 编译器必须能够从函数的参数中推断出来,所以你必须给它一些模式匹配的东西。 在这种情况下,我假设您正在调用const成员函数,并且当编译器模式匹配时,它可以推断T

因为我们有T ,所以我明确地将它提供给PropertiesAre即使我们可以再次推断它。 您的PropertiesAre一个问题是您有扩展参数包的省略号,但它实际上不是可变参数模板。 我通过使R模板参数variadic修复了这个问题。

作为参考,这些是我猜测的定义:

template<typename T>
class Matcher{};

struct Eq
{ Eq(double){} };

template<typename T, typename... X>
Matcher<T> AllOf(X ...x) {}

template<typename P, typename M>
int Property(P p, M m) {}

这个编辑Godbolt

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM