- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我继承了一些看起来像这样的代码:
///
/// A specializable function for converting a user-defined object to a string value
///
template <typename value_type>
std::string to_string(const value_type &value)
{
static_assert(!std::is_same<value_type, value_type>::value, "Unspecialized usage of to_string not supported");
return "";
}
///
/// A specializable function for converting a user-defined object from a string to a value
///
template <typename return_type>
return_type from_string(const std::string &source)
{
static_assert(!std::is_same<return_type, return_type>::value, "Unspecialized usage of from_string not supported");
}
!std::is_same<value_type, value_type>::value
似乎过于冗长。
我是否应该将这些语句更改为 static_assert(false,"...")
?
我不确定以这种方式表达是为了处理某种边缘情况,还是 false
确实是等价的。
是std::is_same<t,t>::value
总是正确的?
最佳答案
您发布的代码格式错误,无需诊断。
将其替换为 static_assert(false, ...)
让编译器注意到您的代码格式不正确。之前的代码格式错误,只是编译器没有注意到它。
我有两个办法可以解决你的问题。一个是黑客,但合法。另一个更简洁,但需要您编写更多代码。
此答案的第一部分是您的代码格式错误的原因。接下来的两个是解决方案。
template <typename value_type>
std::string to_string(const value_type &value)
{
static_assert(!std::is_same<value_type, value_type>::value, "Unspecialized usage of to_string not supported");
return "";
}
to_string
的主模板不能用任何类型实例化。 C++ 标准要求所有模板(包括主模板)都必须具有有效的实例化(在标准语中称为有效特化)。 (还有其他要求,例如如果涉及包,则至少有一个这样的实例必须具有非空包等)。
您可能会提示“编译成功”,但那是不需要诊断的意思。 C++ 标准对编译器在遇到“格式错误且无需诊断”情况下的操作设置零 约束。它可能无法检测到它并愉快地编译“有效”。它可以假定这是不可能的,并且如果确实发生了则生成格式错误的代码。它可以尝试检测它,失败,然后执行上述任一操作。它可以尝试检测它,成功并生成错误消息。它可以检测到并成功生成代码,将您去年在浏览器中查看的每张图片的缩略图通过电子邮件发送给您的所有联系人。
它的格式不正确,不需要诊断。
我自己会避免这样的代码。
现在,有人可能会争辩说有人可以在某个地方专攻 is_same<T,T>
返回 false
,但这也会使您的程序格式错误,因为它是来自 std
的模板的非法特化。违反了标准中对模板的要求。
替换 !std::is_same<value_type, value_type>::value
与 false
只会让您的编译器意识到您的代码格式错误,并生成一条错误消息。从某种意义上说,这是一件好事,因为格式错误的代码将来可能会以任意方式中断。
解决这个问题的愚蠢方法是创建
template<class T, class U>
struct my_is_same:std::is_same<T,U> {};
承认特化漏洞的可能性。这仍然是代码味道。
正确地编写这两种方法需要一些工作。
首先,to_string
和 from_string
基于标签调度而不是模板特化:
namespace utility {
template<class T>struct tag_t {};
template <typename value_type>
std::string to_string(tag_t<value_type>, const value_type &value) = delete;
template <typename value_type>
std::string to_string(const value_type &value) {
return to_string(tag_t<value_type>{}, value);
}
template <typename return_type>
return_type from_string(tag_t<return_type>, const std::string &source) = delete;
template <typename return_type>
return_type from_string(const std::string &source) {
return from_string(tag_t<return_type>{}, source);
}
}
目标是最终用户只需执行 utility::from_string<Bob>(b)
或 utility::to_string(bob)
并且有效。
基本的会反弹到标签分派(dispatch)。要自定义,您需要重载 tag-dispatch 版本。
要在 Bob
的命名空间中实现 to/from 字符串编写这两个函数:
Bob from_string( utility::tag_t<Bob>, const std::string& source );
std::string to_string( utility::tag_t<Bob>, const Bob& source );
注意它们不是模板或模板的特化。
处理 std
中的类型或内置类型,只需在 namespace utility
中定义类似的重载.
现在,ADL 和标记分派(dispatch)将带您到正确的 to/from 字符串函数。无需更改 namespace 来定义到/从字符串。
如果您调用 to_string
或 from_string
没有有效的 tag_t
过载,你最终会调用 =delete
并收到“未找到过载”错误。
测试代码:
struct Bob {
friend std::string to_string( utility::tag_t<Bob>, Bob const& ) { return "bob"; }
friend Bob from_string( utility::tag_t<Bob>, std::string const&s ) { if (s=="bob") return {}; exit(-1); }
};
int main() {
Bob b = utility::from_string<Bob>("bob");
std::cout << "Bob is " << utility::to_string(b) << "\n";
b = utility::from_string<Bob>( utility::to_string(b) );
std::cout << "Bob is " << utility::to_string(b) << std::endl;
Bob b2 = utility::from_string<Bob>("not bob");
std::cout << "This line never runs\n";
(void)b2;
}
(不需要使用 friend
,该函数只需与 Bob
位于相同的命名空间中或位于 namespace utility
内)。
关于c++ - std::is_same<t,t>::value 总是为真吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44847559/
我对这个错误很困惑: Cannot implicitly convert type 'System.Func [c:\Program Files (x86)\Reference Assemblies\
考虑这段代码: pub trait Hello { fn hello(&self); } impl Hello for Any { fn hello(&self) {
问题很简单。是否可以构造这样一个类型 T,对于它下面的两个变量声明会产生不同的结果? T t1 = {}; T t2{}; 我已经研究 cppreference 和标准一个多小时了,我了解以下内容:
Intellij idea 给我这个错误:“Compare (T, T) in Comparator cannot be applied to (T, T)” 对于以下代码: public class
任何人都可以告诉我 : n\t\t\t\t\n\t\t\t 在以下来自和 dwr 服务的响应中的含义和用途是什么. \r\n\t\t\t \r\n\t\t\t
让 T 成为一个 C++ 类。 下面三个指令在行为上有什么区别吗? T a; T a(); T a = T(); T 为不带参数的构造函数提供了显式定义这一事实是否对问题有任何改变? 后续问题:如果
Rust中的智能指针是什么 智能指针(smart pointers)是一类数据结构,是拥有数据所有权和额外功能的指针。是指针的进一步发展 指针(pointer)是一个包含内存地
比如我有一个 vector vector > v={{true,1},{true,2},{false,3},{false,4},{false,5},{true,6},{false,7},{true,8
我有一个来自 .xls 电子表格的数据框,我打印了 print(df.columns.values) 列,输出包含一个名为:Poll Responses\n\t\t\t\t\t。 我查看了 Excel
This question already has answers here: What are good reasons for choosing invariance in an API like
指针类型作为类型前缀与在类型前加斜杠作为后缀有什么区别。斜线到底是什么意思? 最佳答案 语法 T/~ 和 T/& 基本上已被弃用(我什至不确定编译器是否仍然接受它)。在向新向量方案过渡的初始阶段,[T
我正在尝试找到一种方法来获取模板参数的基类。 考虑以下类: template class Foo { public: Foo(){}; ~Foo(){};
这是一个让我感到困惑的小问题。我不知道如何描述它,所以只看下面的代码: struct B { B() {} B(B&) { std::cout ::value #include
为什么有 T::T(T&) 而 T::T(const T&) 更适合 copy ? (大概是用来实现move语义的???) 原始描述(被melpomene证明是错误的): 在C++11中,支持了一种新
在 Java 7 中使用 eclipse 4.2 并尝试实现 List 接口(interface)的以下方法时,我收到了警告。 public T[] toArray(T[] a) { ret
假设有三个函数: def foo[T](a:T, b:T): T = a def test1 = foo(1, "2") def test2 = foo(List(), ListBuffer()) 虽
我对柯里化(Currying)和非柯里化(Currying)泛型函数之间类型检查的差异有点困惑: scala> def x[T](a: T, b: T) = (a == b) x: [T](a: T,
考虑一个类A,我如何编写一个具有与相同行为的模板 A& pretty(A& x) { /* make x pretty */ return x; } A pretty(A&& x) {
Eclipse 表示由于泛型类型橡皮擦,类型参数不允许使用 instanceof 操作。 我同意在运行时不会保留任何类型信息。但是请考虑以下类的通用声明: class SomeClass{ T
在 C++14 中: 对于任何整数或枚举类型 T 以及对于任何表达式 expr: 有没有区别: struct S { T t { expr }; }; 和 struct S { T t = { exp
我是一名优秀的程序员,十分优秀!