如何解决std::enable_if 在字符串文字和 const char* 上的行为不同
出于某种原因,我包装 std::cin
以使其能够接受可调用对象,即首先执行它并在传入可调用对象时打印返回值。经过一番搜索,我知道这可以通过 SFINAE 来完成,这是一种我不熟悉的技术。我修改了一个问题的代码,我现在找不到链接。简化代码:
class llogger{
public:
template <typename T>
llogger& operator << (const T& content);
private:
template <typename T>
void opImpl(const T& content,std::true_type tp);
template <typename T>
void opImpl(const T& content,std::false_type tp);
};
template <typename T,typename = void>
struct is_callable : public std::false_type {};
template <typename T>
struct is_callable<
T,std::enable_if_t<!std::is_same_v<void,std::invoke_result_t<T()>>>>
: public std::true_type {};
template <typename T>
void llogger::opImpl(const T& content,std::false_type tp){
std::cout << content;
}
template <typename T>
void llogger::opImpl(const T& content,std::true_type tp){
std::cout << content();
}
template <typename T>
llogger& llogger::operator << (const T& content){
opImpl(content,is_callable<T>{});
return *this;
}
当传递字符串文字时,它按预期工作:
llogger LL;
LL << "test";
//prints "test"
它可以识别可调用对象并选择正确的重载:
LL << []{return "test";};
//prints "test"
但是当传递除字符串文字或 const char[]
以外的任何内容时,编译时会发生错误,即使该值是 const char*
:
const char* s = "test";
LL << s;
/*
In instantiation of ‘void llogger::opImpl(const T&,std::true_type) [with T = const char*; std::true_type = std::integral_constant<bool,true>]’:
required from ‘llogger& llogger::operator<<(const T&) [with T = const char*]
required from here
error: expression cannot be used as a function
std::cout << content();
~~~~~~~^~
*/
为了更清楚,我尝试传递 const char*
文字、const char[]
、const char*
、char
文字和 char
、std::string
和 {{ 1}},只有 int
文字和 const char*
可以通过编译而不会出错。
谁能告诉我为什么会这样?实现我的目标的最佳实践是什么(为返回非空值的可调用对象选择适当的重载)?
gcc 版本:10.2.0,使用标志 const char[]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。