gpt4 book ai didi

c++ - 模板特征类中枚举和静态常量成员变量的使用

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:28:59 24 4
gpt4 key购买 nike

我想测试一个类是否可以流式传输到 ostream&通过查看 operator<< 是否过载提供。基于these posts ,我尝试使用 C++11 编写另一个版本。这是我的尝试:

#include <iostream>
#include <type_traits>

namespace TEST{
class NotDefined{};

template<typename T>
NotDefined& operator << (::std::ostream&, const T&);

template <typename T>
struct StreamInsertionExists {
static std::ostream &s;
static T const &t;
enum { value = std::is_same<decltype(s << t), NotDefined>() };
};
}

struct A{
int val;
friend ::std::ostream& operator<<(::std::ostream&, const A&);
};

::std::ostream& operator<<(::std::ostream& os, const A& a)
{
os << a.val;
return os;
}

struct B{};

int main() {
std::cout << TEST::StreamInsertionExists<A>::value << std::endl;
std::cout << TEST::StreamInsertionExists<B>::value << std::endl;

}

但是编译失败:

test_oper.cpp:40:57: error: reference to overloaded function could not be resolved; did you mean to call it?  
std::cout << TEST::StreamInsertionExists<A>::value << std::endl;

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ostream:1020:1: note:
possible target for call
endl(basic_ostream<_CharT, _Traits>& __os)

test_oper.cpp:30:17: note: candidate function not viable: no known conversion from 'TEST::NotDefined' to '::std::ostream &'
(aka 'basic_ostream<char> &') for 1st argument
::std::ostream& operator<<(::std::ostream& os, const A& a)

test_oper.cpp:15:15: note: candidate template ignored: couldn't infer template argument 'T'
NotDefined& operator << (::std::ostream&, const T&);

但是,如果我更换行
enum { value = std::is_same<decltype(s << t), NotDefined>() };

static const bool value = std::is_same<decltype(s << t), NotDefined>();
然后一切编译。

为什么 enum 之间会有这样的差异?和 bool

最佳答案

valueStreamInsertionExists<T> 中匿名名称的枚举.当您尝试这样做时:

std::cout << StreamInsertionExists<T>::value;

编译器正在对 operator<<(std::ostream&, StreamInsertionExists<T>::E) 进行重载查找.在典型情况下,它会对 enum 进行积分提升。并将其流式传输为 int .但是,您另外定义了这个运算符:

template<typename T> 
NotDefined& operator << (std::ostream&, const T&);

这更适合 enumint version (Exact Match vs integral promotion),所以首选。是的,它是一个函数模板,但只有在转换序列匹配时才首选非模板 - 而在这种情况下它们不匹配。

因此,这一行:

std::cout << TEST::StreamInsertionExists<A>::value << std::endl;

即:

operator<<(operator<<(std::cout, TEST::StreamInsertionExists<A>::value), std::endl);

和最里面operator<<通话将使用您的 NotDefined&模板。因此,下一步将是找到一个合适的函数调用:

operator<<(NotDefined&, std::endl);

operator<< 没有这样的重载因此错误。

如果你改变value成为bool ,没有这样的问题,因为一个operator<<这需要 bool正是:#6 .也就是说,即使有 bool ,你的特征仍然不正确,因为它总是返回 false .你的NotDefined version 实际上返回一个引用,所以你必须检查它。还有,NotDefined&表示定义,因此您必须翻转标志:

static const bool value = !std::is_same<decltype(s << t), NotDefined&>();

但是,这特别容易出错。现在cout << B{};而不是编译失败反而会给你一个链接器错误,并且 cout << B{} << endl;给你同样令人困惑的过载错误,涉及 endl而不是简单地声明你不能流式传输 B .

你应该更喜欢这样做:

template <typename...>
using void_t = void;

template <typename T, typename = void>
struct stream_insertion_exists : std::false_type { };

template <typename T>
struct stream_insertion_exists<T, void_t<
decltype(std::declval<std::ostream&>() << std::declval<T>())
> > : std::true_type { };

关于c++ - 模板特征类中枚举和静态常量成员变量的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30277392/

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