我一直在尝试根据是否operator<<(std::ostream&, const T&)存在过载来在两个模板化函数之间进行选择.
例:
template <typename T, typename std::enable_if</* ? */, int>::type = 0>
std::string stringify(const T& t)
{
std::stringstream ss;
ss << t;
return ss.str();
}
template <typename T, typename std::enable_if</* ? */, int>::type = 0>
std::string stringify(const T& t)
{
return "No overload of operator<<";
}
struct Foo { };
int main()
{
std::cout << stringify(11) << std::endl;
std::cout << stringify(Foo{}) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这可能吗?如果是这样,你会如何解决这个问题?
Pra*_*ian 18
当存在时,不需要enable_if使用表达式SFINAE来选择正确的过载operator<<.
namespace detail
{
template<typename T>
auto stringify(std::stringstream& ss, T const& t, bool)
-> decltype(ss << t, void(), std::string{})
{
ss << t;
return ss.str();
}
template<typename T>
auto stringify(std::stringstream&, T const&, int)
-> std::string
{
return "No overload of operator<<";
}
}
template <typename T>
std::string stringify(const T& t)
{
std::stringstream ss;
return detail::stringify(ss, t, true);
}
Run Code Online (Sandbox Code Playgroud)
该stringify函数模板只是代表们的一个detail::stringify函数模板.然后,如果表达式ss << t格式正确,则选择第一个.未命名的bool参数用于两个detail::stringify实现之间的消歧.由于主stringify函数true作为参数传递detail::stringify,因此当operator<<存在重载时,第一个函数将是更好的匹配.否则将选择第二个.
decltype(ss << t, void(), std::string{})第一个stringify模板的尾随返回类型中的此表达式可能需要更详细的解释.这里我们有一个表达式,由3个由逗号运算符分隔的子表达式组成.
第一个ss << t是确定该函数模板是否通过模板参数替换并将被添加到重载决策集的内容.如果表达式格式正确,即如果所讨论的类型超载,则会发生这种情况operator<<.
中间子表达式void()除了确保operator,未选择某些用户定义之外不执行任何操作(因为您不能operator,使用void参数类型重载).
第三个也是最右边的子表达式std::string{}决定了detail::stringify函数的返回类型.
| 归档时间: |
|
| 查看次数: |
1608 次 |
| 最近记录: |