【问题标题】:How to fail static_assert on function use如何在函数使用时使 static_assert 失败
【发布时间】:2018-03-29 13:45:04
【问题描述】:

当我尝试打印一个类的实例时,我希望编译器抱怨, 假设T2。在 VS2013+ 中我可以使用:

template <typename T = float>
std::ostream & operator<<(std::ostream & os, const T2 & t2) {
    static_assert(std::is_integral<T>::value, "Fail in << for T2");
    return os;
}

但是,这在 VS2012 (error C4519: default template arguments are only allowed on a class template) 中不起作用。任何想法如何在 VS2012 中实现这一点?

【问题讨论】:

  • 似乎错误没有提到 static_assert 但默认模板参数 typename T = float
  • 好吧,但这就是问题所在;没有template &lt;...&gt;,它完全无法编译,断言失败,因为该函数立即实例化,static_assert 失败:/
  • 在 MSVC 2017 之前,模板在那些编译器中基本上被破坏了。从 2017 年开始,情况会更好:它只是不合规。
  • 我现在确实了解您的问题,我想警告您。即使您可以让 MSVC 接受该代码,它也会在您编写例如 std::cout &lt;&lt; "not integral lol" 时被完全忽略:请参阅此问题:stackoverflow.com/q/527742/5470596
  • 嗯,我有工作超载被调用。所以那部分正在工作。现在我只想让编译失败 if 它被调用。那部分我无法在 VS2012 下工作。 Tbh 我不确定链接的问题与这里的相关性:/

标签: c++ visual-studio-2012


【解决方案1】:

VS2012 对 C++11 的支持不完全。支持函数模板的默认模板参数,作为 C++11 特性,starting with VS2013

也许你可以试试这个,但它也使用了一些 C++11 特性:

template <typename T>
auto operator<<(std::ostream & os, T const& t2) ->
    typename std::enable_if<std::is_same<T, T2>::value, std::ostream&>::type  
{
    static_assert(false, "Fail in << for T2");
    return os;
}

如果这也不起作用,我会优雅地降级为像 VS2012 这样的古老垃圾并完成它。

#if _MSC_VER < 1800
std::ostream& operator<<(std::ostream & os, T2 const& t2); // will fail at link time
#else
. . .
#endif

【讨论】:

  • 链接时间错误是可行的。我希望在构建日志中添加一些自定义错误消息,但是,这总比没有好,谢谢 :) 如果没有人提供更聪明的方法会接受这个
  • 这就是 SFINAE 部分的用途。你试过了吗?
  • 是的,很抱歉我没有正确阅读它,我现在注意到它并尝试了它,似乎可以正常工作,可能吗? :) 很聪明,没想到这样
【解决方案2】:

“我希望编译器在我尝试打印一个实例时抱怨 班级,比如说T2”

#include <iostream>

struct T1 { int a; };
struct T2 { int a; };

template <typename T>
std::ostream & operator<<(std::ostream & os, const T & t2) 
{
    static_assert(!std::is_same<T2, T>::value, "Fail in << for T2");
    return os;
}

int main()
{
    T1 t1;
    T2 t2;
    std::cout << t1; // Works
    std::cout << t2; // Static assert fail
}

我不明白。这不能回答你的问题吗?

【讨论】:

  • 问题是这增加了“catch-all”输出操作符。当我稍后添加T3 时,它只会将std::cout &lt;&lt; T3(); 变成无操作(准确地说是... { return os; })。哪个不理想...
猜你喜欢
  • 1970-01-01
  • 2017-08-22
  • 2018-04-26
  • 1970-01-01
  • 2016-04-17
  • 2021-07-23
  • 2022-11-22
  • 1970-01-01
  • 2023-04-04
相关资源
最近更新 更多