如何在命名空间内增加枚举

时间:2016-08-29 09:45:00

标签: c++ c++11 enums googletest

我有一个这样的枚举:

namespace api {
    enum Operation {
        INSERT =1,
        UPDATE =2,
        DELETE =3,
    };

    const Operation Operation_MIN = INSERT;
    const Operation Operation_MAX = DELETE;
} // api

我想写一些使用它的测试:

#include "gtest.h"
class FWTest : public ::testing::Test {};

class FWTestPar : public FWTest, public ::testing::WithParamInterface<api::Operation>
{};

INSTANTIATE_TEST_CASE_P(Piping, FWTestPar, ::testing::Range(
    api::Operation_MIN, api::Operation_MAX+1)
);

为了能够增加枚举,我写了这个运算符:

template <typename E>
constexpr typename std::enable_if<std::is_enum<E>::value, E>::type
operator+(E val, int step)
{
    return static_cast<E>(static_cast<int>(val) + step);
}

使用G ++从4.8到6.2编译好,但是clang拒绝查找operator+

clang++ -g -std=c++14 -Wall -pedantic -Wextra -Wformat=2 -I ~/workspace/zarquon -o "enum_inc_real" "enum_inc_real.cc" (in directory: /tmp)
In file included from enum_inc_real.cc:1:
third_party/gmock/gtest/gtest.h:10250:34: error: assigning to 'api::Operation' from incompatible type 'int'
    for (T i = begin; i < end; i = i + step)
                                 ^ ~~~~~~~~
third_party/gmock/gtest/gtest.h:10191:33: note: in instantiation of member function 'testing::internal::RangeGenerator<api::Operation, int>::CalculateEndIndex' requested here
        step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
                                ^
third_party/gmock/gtest/gtest.h:15815:11: note: in instantiation of member function 'testing::internal::RangeGenerator<api::Operation, int>::RangeGenerator' requested here
      new internal::RangeGenerator<T, IncrementT>(start, end, step));
          ^
third_party/gmock/gtest/gtest.h:15820:10: note: in instantiation of function template specialization 'testing::Range<api::Operation, int>' requested here
  return Range(start, end, 1);
         ^
enum_inc_real.cc:34:55: note: in instantiation of function template specialization 'testing::Range<api::Operation>' requested here
INSTANTIATE_TEST_CASE_P(Piping, FWTestPar, ::testing::Range(
                                                      ^
In file included from enum_inc_real.cc:1:
third_party/gmock/gtest/gtest.h:10213:14: error: assigning to 'api::Operation' from incompatible type 'int'
      value_ = value_ + step_;
             ^ ~~~~~~~~~~~~~~
third_party/gmock/gtest/gtest.h:10204:5: note: in instantiation of member function 'testing::internal::RangeGenerator<api::Operation, int>::Iterator::Advance' requested here
    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
    ^
third_party/gmock/gtest/gtest.h:10195:16: note: in instantiation of member function 'testing::internal::RangeGenerator<api::Operation, int>::Iterator::Iterator' requested here
    return new Iterator(this, begin_, 0, step_);
               ^
third_party/gmock/gtest/gtest.h:10189:3: note: in instantiation of member function 'testing::internal::RangeGenerator<api::Operation, int>::Begin' requested here
  RangeGenerator(T begin, T end, IncrementT step)
  ^
third_party/gmock/gtest/gtest.h:15815:11: note: in instantiation of member function 'testing::internal::RangeGenerator<api::Operation, int>::RangeGenerator' requested here
      new internal::RangeGenerator<T, IncrementT>(start, end, step));
          ^
third_party/gmock/gtest/gtest.h:15820:10: note: in instantiation of function template specialization 'testing::Range<api::Operation, int>' requested here
  return Range(start, end, 1);
         ^
enum_inc_real.cc:34:55: note: in instantiation of function template specialization 'testing::Range<api::Operation>' requested here
INSTANTIATE_TEST_CASE_P(Piping, FWTestPar, ::testing::Range(
                                                      ^

如果在operator+命名空间内定义了模板api,则clang ++也接受此代码。

那么,哪个编译器是对的?

我是否真的必须将operator+拖到包含我想要增加的枚举的每个命名空间中?

奇怪的是,gtest做了类似的事情:

namespace testin_ {
    namespace intl {
        template<typename T>
        class PII {};

        template<typename T, typename Inc>
        class RG{
        public:
            RG(T begin, T end, Inc s)
            : begin_{begin}, end_{end}, step_{s}, end_index_{CalculateEndIndex(begin, end, s)}
            {}

            T begin() { return begin_; }
            T end  () { return end_;   }
        private:

        class It : public PII<T> {
            void advance() {
                value_ = value_ + step_;
            }

            T   value_;
            int index_;
            Inc step_;
        };
        static int CalculateEndIndex(const T& begin,
                                     const T& end,
                                     const Inc& step) {
          int end_index = 0;
          for (T i = begin; i < end; i = i + step)
            end_index++;
          return end_index;
        }

            const T begin_;
            const T end_;
            const Inc step_;
            const int end_index_;
        };
    } // intl

    template<typename T, typename Inc>
    intl::RG<T, Inc> Rg(T start, T end, Inc step) {
        return intl::RG<T, Inc>(start, end, step);
    }
}

auto gen = testin_::Rg(api::INSERT, api::DELETE, 1);

在没有clang ++投诉的情况下被接受

0 个答案:

没有答案