SFINAE使基本模板始终导致错误 [英] SFINAE to make base template always result in error

查看:57
本文介绍了SFINAE使基本模板始终导致错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我正在设计一种 my_numeric_cast 函数,以限制使用我正在编写的框架时可用的转换类型。

So I'm designing a sort of my_numeric_cast function to limit the types of conversions available when using a framework I'm writing.

直接做类似的事情

template<typename To, typename From>
constexpr To my_numeric_cast(From);

template<>
constexpr float my_numeric_cast<float, int>(int i) { return i; }

这是可行的,只要使用强制类型转换,仅允许从整数类型转换为浮点型。每当尝试进行不在白名单中的转换时,都会产生链接错误。

Which works, allowing only casting from ints to floats whenever the cast is used. And producing a linkage error whenever a cast not in the white list is attempted.

但是,我真的很想使它成为编译错误,以防引起滥用

如何使基本模板主体有效,实例化时会期望它?

However, I'd really want to make this a compilation error, to catch the misuse much faster.
How do I make the base template body valid, expect when instantiating it?

推荐答案

您无法编写没有模板参数可以使主体在C ++中有效的模板函数专用化。如果这样做,结果将是一个格式错误的程序,不需要进行诊断。

You cannot write a template function specialization for which no template argument makes the body valid in C++. The result if you do so is an ill formed program with no diagnostic required. This includes the primary specialization.

因此,这里的大多数答案都是不确定的行为。它们可能有效,但是它们不是有效的C ++。它们可能在今天可用,但是在库升级,编译器升级或其他构建目标之后,它们可能会以完全不同且令人惊讶的方式失败。

So most of the answers here are simply undefined behaviour. They may work, but they are not valid C++. They may work today, but after a library upgrade a compiler upgrade or a different build target they could fail in completely different and surprising ways. Relying on UB with no strong reason is a bad idea.

从好的方面来说,我们可以消除模板的专门化,并一口气解决您的问题:

On the plus side, we can do away with template specialization and fix your problem in one fell swoop:

template<class T>struct tag_t{}; // may need `constexpr tag_t(){}` on some compilers
template<class T>constexpr tag_t<T> tag{};

template<class T, class F>
constexpr T my_numeric_cast(F, tag_t<F>)=delete; // generates compile time error

constexpr float my_numeric_cast(int i, tag_t<float>) { return i; } // not a template!  Could be if you want it to be.

template<typename To, typename From>
constexpr To my_numeric_cast(From f){
  return my_numeric_cast(f, tag<To>);
}

并完成。

=删除会生成友好消息。程序格式正确。实施强制转换不再是一种专业。您甚至可以在启用ADL的情况下,在要转换为类型的名称空间中实现它。

=delete generates friendly messages. Program is well formed. Implementing casts is no longer a specialization. You can even implement it in the namespace of a type being cast to or from as ADL is enabled.

如果您解决了模板功能专门化的问题,请重新考虑。它们很脆弱,不能像类模板专业化或函数重载一样工作(虽然看起来像它们两者!),并且通常不是解决任何问题的最佳方法。虽然有个例外,但这也许是个好主意,但它们很少见,并且鉴于避免这种古怪功能的难得之处,仍然值得。

If you solve a problem with template function specialization, reconsider. They are fragile, do not work like class template specialization or function overloading (while looking like both of them!), and usually are not the best solution to anything. There are exceptions when it may be a good idea, but they are quite rare, and given how rare they are avoiding the quirky feature may still be worth it.

这篇关于SFINAE使基本模板始终导致错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆