Разница между статическим кортежем constexpr внутри и снаружи класса - PullRequest
0 голосов
/ 18 октября 2018

Я использую 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_ tuple нет.,

Я бы хотел создать кортеж с make_tuple, чтобы избежать необходимости указывать аргументы для std :: tuple.

Любое возможное объяснение этого поведения?

1 Ответ

0 голосов
/ 18 октября 2018

Это стандартное поведение C ++ 11.Хотя elements_ это constexpr, это не определение.Декларации статических членов никогда не являются определениями до C ++ 17.Если вы используете ODR (например, связываете его со ссылкой), должно быть определение вне класса.

Простой обходной путь - добавить это ...

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

... в некоторый исходный файл, создайте объект и свяжите его.

...