在调试配置中使用 gcc 初始化静态 constexpr 自制字符串变量时出现未定义符号,C++14

问题描述 投票:0回答:1

我无法理解 C++14 中的链接器错误

gcc

我的目的是拥有一个根据非类型模板参数(一种值和字符串之间的编译时映射)公开名称的模板。
C++14 中缺乏对
constexpr
字符串的支持。我围绕静态纯 C 字符串实现了一个非常基本的包装器:
在 header.h 中

#ifndef HEADER
#define HEADER
#include <cstddef>
#include <ostream>

namespace nConstStr
{
class constStr
{
public:
    constexpr constStr() noexcept = default;
    constexpr constStr(constStr const& str) noexcept :
        _str(str._str), _sz(str._sz)
    {
    }
    template<std::size_t N>
    constexpr explicit constStr(char const (&str)[N]) noexcept :
        _str(str), _sz(N - 1)
    {
    }
    ~constStr() noexcept = default;
    constexpr char operator[](std::size_t const i) const noexcept
    {
        return _str[i];
    }
    constexpr std::size_t size() const noexcept
    {
        return _sz;
    }

private:
    char const* _str = nullptr;
    std::size_t _sz = 0;
};
std::ostream& operator<<(std::ostream& os, constStr const& str)
{
    for (std::size_t i = 0; i < str.size(); ++i)
    {
        os << str[i];
    }
    return os;
}
}

template<std::size_t I> class dummy final
{
public:
    static constexpr nConstStr::constStr name = nConstStr::constStr{"dummy"};
};

#endif

为了简单起见,这里的字符串始终是相同的。 然后我有一个翻译单元,我正在使用这个:
在测试.cpp中

void test() {
    // injecting my overloaded operator<<
    using nConstStr::operator<<;
    std::cout << dummy<42>::name << '\n';
}

我从

main
打电话。

在调试配置中使用 C++14 中的 gcc 进行编译时,出现链接错误:

src.cpp:8:对 `dummy<42ul>::name'

的未定义引用

直播

在我的机器上,它编译并运行良好

-O2

它也适用于 C++17 或更高版本。

注意,

MSVC
接受代码,但
clang
似乎与
gcc
一致(至少在godbolt上,无法在本地测试)。

c++ templates linker c++14 undefined-reference
1个回答
0
投票

类模板

dummy
需要有
inline
name
定义:

static inline constexpr nConstStr::constStr name = nConstStr::constStr{"dummy"};
       ^^^^^^
© www.soinside.com 2019 - 2024. All rights reserved.