class 内部和外部静态 constexpr 元组的区别
difference between static constexpr tuple inside and outside a class
我正在使用带有 C++11 的 gcc 4.8.5,我试图了解以下行为是否正常,或者它是否是 C++11 限制/编译器错误。
基本上,如果我在 class 中定义一个 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 指定参数。
对此行为有任何可能的解释吗?
这是标准的 C++11 行为。尽管 elements_
是 constexpr
,但它不是定义。静态成员声明从不是 C++17 之前的定义。如果您使用 ODR(例如通过将其绑定到引用),则必须有一个超出 class 的定义。
一个简单的解决方法是添加这个...
constexpr decltype(ObjectInfo::elements_) ObjectInfo::elements_;
...进入某个源文件,构建一个对象并link它。
我正在使用带有 C++11 的 gcc 4.8.5,我试图了解以下行为是否正常,或者它是否是 C++11 限制/编译器错误。
基本上,如果我在 class 中定义一个 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 指定参数。
对此行为有任何可能的解释吗?
这是标准的 C++11 行为。尽管 elements_
是 constexpr
,但它不是定义。静态成员声明从不是 C++17 之前的定义。如果您使用 ODR(例如通过将其绑定到引用),则必须有一个超出 class 的定义。
一个简单的解决方法是添加这个...
constexpr decltype(ObjectInfo::elements_) ObjectInfo::elements_;
...进入某个源文件,构建一个对象并link它。