为什么这个const类型的模板会出错?

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

感谢阅读这个问题。

代码在这里。版本 C++17

#include <iostream>
#include <memory>
#include <queue>

template<typename TValue>
[[maybe_unused]]
constexpr auto t1(const std::queue<TValue> &value) -> void {
    std::queue<TValue> temp = value;
    while (!temp.empty()) {
        std::cout << temp.front() << std::endl;
        temp.pop();
    }
}

template<typename TValue>
constexpr auto t1(const TValue &nm) -> void {
    std::cout << nm << std::endl;
}

template<typename TValue>
constexpr auto t1(const std::shared_ptr<TValue> &nm) -> void {
    t1<TValue>(*nm);
}


int main(int argc, char **argv) {
    std::shared_ptr<const std::string> s_ptr = std::make_shared<const std::string>("test");
    t1(s_ptr);

    return 0;
}

这段代码会抛出一个错误: enter image description here

我尝试使用shared_ptr更改模板,例如:

template<typename TValue>
constexpr auto t1(const std::shared_ptr<TValue> &nm) -> void {
    TValue temp = *nm;
    t1<TValue>(temp);
}

但它犯了同样的错误。

然后我尝试获取“TValue”类型:

template<typename TValue>
constexpr auto t1(const std::shared_ptr<TValue> &nm) -> void {
    if constexpr (std::is_same_v<TValue, const std::string>){
        static_assert(false, "??");
    }
    t1<TValue>(*nm);
}

static_assert 被触发。这意味着 'TValue' 只是 'const std::string'。

不小心,我像这样删除了

<TValue>

template<typename TValue>
constexpr auto t1(const std::shared_ptr<TValue> &nm) -> void {
    t1(*nm);
}

或者:

template<typename TValue>
constexpr auto t1(const std::shared_ptr<TValue> &nm) -> void {
    t1<std::remove_cv_t<TValue>>(*nm);
}

它有效。

那么当有

<TValue>
时,为什么模板要将 const std::string 转换为 std::queue ??? 谢谢你的回答。

c++ templates c++17 std shared-ptr
1个回答
0
投票

问题在于您显式提供了模板参数

TValue
,这会导致
std::deque<const std::string>
的实例化。
std::deque<T>
需要一个非常量、非易失性
T
,正如失败的静态断言所示:

错误:静态断言失败:

std::deque
必须具有非常量、非易失性
value_type

解决方案

您可以写

t1(*nm)
来代替。 这里的区别在于
std::deque<const std::string>
永远不会被实例化。 相反,替换为
t1(std::deque)
将会失败,因为
*nm
const std::string
并且
TValue
中的
std::deque<TValue>
无法从
const std::string
推导出来。

template<typename TValue>
constexpr auto t1(const std::shared_ptr<TValue> &nm) -> void {
    t1(*nm); // OK
}
© www.soinside.com 2019 - 2024. All rights reserved.