类内外的静态constexpr元组之间的区别

时间:2018-10-18 07:38:50

标签: c++ tuples template-meta-programming constexpr undefined-reference

我正在将gcc 4.8.5与C ++ 11一起使用,并且试图了解以下行为是否正常,或者是否为C ++ 11限制/编译器错误。

基本上,如果我在类中定义了constexpr元组,则会收到未定义的引用错误,但如果是全局定义,则不会。

以下是完整的测试代码:

// file foo.h
#pragma once
#include <tuple>

struct ObjectStruct
  {
  int a;
  int b;
  };

static constexpr auto g_elements_ = std::make_tuple(
  1,
  2);

struct ObjectInfo
  {
  static constexpr auto elements_ = std::make_tuple(
    1,
    2);
  };

// File tuple_iterator.h
#pragma once
#include <tuple>
template<class Object, class Value, std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
  iterateT(Object& object, const std::tuple<Tp...>& t, Value value)
  {
  std::cout << "base: " << std::to_string(I) << std::endl;
  }

template<class Object, class Value, std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
  iterateT(Object& object, const std::tuple<Tp...>& t, Value value)
  {
    std::cout << "N: " << std::to_string(I) << std::endl;
    auto ele = std::get<I>(t);
    // DO something with ele
    iterateT<Object, Value, I + 1, Tp...>(object, t, value);
  }

// file main.cpp
#include <iostream>
#include "foo.h"
#include "tuple_iterator.h"
using namespace std;

int
main ()
{
  ObjectStruct object;
  iterateT (object, ObjectInfo::elements_, 5);
  iterateT (object, g_elements_, 5);

  return 0;
}

我收到错误:未定义对ObjectInfo :: elements _

的引用

正如我所说,全局g_elements_元组没有错误。

我想用make_tuple创建一个元组,而不必为std :: tuple指定参数。

对此行为有任何可能的解释吗?

1 个答案:

答案 0 :(得分:3)

这是标准的C ++ 11行为。即使elements_constexpr,它也不是一个定义。静态成员声明绝不是C ++ 17之前的定义。如果您使用ODR(例如,将其绑定到引用),则必须存在类外定义。

一个简单的解决方法是将其添加...

constexpr decltype(ObjectInfo::elements_) ObjectInfo::elements_;

...到某个源文件中,构建一个对象并将其链接。