gpt4 book ai didi

c++ - 模板化代码中的函数调用歧义

转载 作者:行者123 更新时间:2023-12-04 02:25:14 24 4
gpt4 key购买 nike

这是一个(非常精炼的)用例和代码示例(很抱歉,如果它看起来不太简单,我想不出还有什么要排除的。完整的“只编译”代码可以在这里找到:https://gcc.godbolt.org/z/5GMEGKG7T )

我想要一个“特殊”的输出流,对于某些用户类型,它在流处理期间进行特殊处理。

这个特殊流应该能够流式传输具有“特殊”处理的“特殊”类型,以及可以通过常规流进行流式传输的任何其他类型——在后一种情况下,我们只需直接使用常规流

struct Type { }; // Special type

struct Stream { // Special stream

// In this distilled example, we could achieve the same result
// by overriding << for ostream and Type, but the actual use case is wider
// and requires usage of the special stream type
// For illustration purposes only, we use this overload to cout "T!" for Types
Stream& stream(Type t) { std::cout << "T!"; return *this;}

// For any type for which cout << T{} is a valid operation, use cout for streaming
template<class T>
auto stream(const T& t) -> decltype(std::cout << std::declval<T>(), std::declval<Stream&>())
{
std::cout << t; return *this;
}
};

// Consumes every T for which Stream.stream is defined - those would be Type
// as well as anything else which can be sent to cout
template<class T>
auto operator<<(Stream& s, const T& t) -> decltype(s.stream(t))
{
s.stream(t);
return s;
}

此代码按预期工作:

void foo()
{
Stream stream;
stream << 10 << Type{};
}

现在我想定义一个不同的结构,其中有一个 Type 的成员,以及一个用于同一结构的流操作符:

struct Compound {
Type t;
int i;
};

// We want the `<<` operator of the struct templated, because we want it to work with
// any possible stream-like object out there
template<class S>
S& operator<<(S& s, Compound comp)
{
s << comp.t << " " << comp.i;

return s;
};

不幸的是,这并不能很好地工作。尝试使用此 << 运算符:

void bar(Compound comp)
{
Stream s;
s << comp;
}

引发歧义:

error: ambiguous overload for 'operator<<' (operandtypes are 'Stream' and 'Compound')

note: candidate: 'decltype (s.Stream::stream(t)) operator<<(Stream&, const T&)

note: candidate: 'S& operator<<(S&, Compound) [with S = Stream]'

这是有道理的,因为在为 << 定义了 Compound 的模板化运算符之后,它可以通过 cout 以及通过这个新运算符进行流式传输!

我当然可以通过为 << 设置非模板化的 Compound 来解决这个问题,而是使用特殊的 Stream 作为流参数 - 但我想避免它。

有没有一种方法可以为 << 保留模板化的 Compound 并且仍然避免歧义?

最佳答案

所以你需要降低operator<<(Stream& s, const T& t)的优先级使其成为最后的手段。

您可以通过对第一个参数进行模板化来使其(看起来)不那么特化:

auto operator<<(std::same_as<Stream> auto &s, const auto &t) -> decltype(s.stream(t))
{
s.stream(t);
return s;
}

我对第二个参数所做的更改并不重要,只是为了简洁。

关于c++ - 模板化代码中的函数调用歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68291738/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com