没有参考书,任何人都可以CRTP用代码示例提供一个很好的解释吗?
void*在C++中是否合法使用?或者这是因为C有它吗?
只是回顾一下我的想法:
输入:如果我们想要允许多个输入类型,我们可以重载函数和方法,或者我们可以定义一个公共基类或模板(感谢在答案中提到这一点).在这两种情况下,代码都更具描述性并且更不容易出错(假设基类以合理的方式实现).
输出:我想不出任何我希望接收的情况 void*,而不是从已知基类派生的东西.
只是为了说明我的意思:我没有具体询问是否有用例void*,但是如果有一个案例void*是最好的或唯一可用的选择.以下几个人已经完全回答了这个问题.
今天早上问的这个问题让我想知道你认为C++标准库中缺少哪些功能,以及你如何用填充函数填补空白.例如,我自己的实用程序库具有此向量追加功能:
template <class T>
std::vector<T> & operator += ( std::vector<T> & v1,
const std::vector <T> & v2 ) {
v1.insert( v1.end(), v2.begin(), v2.end() );
return v1;
}
Run Code Online (Sandbox Code Playgroud)
这个用于清除(或多或少)任何类型 - 特别适用于像std :: stack这样的东西:
template <class C>
void Clear( C & c ) {
c = C();
}
Run Code Online (Sandbox Code Playgroud)
我还有一些,但我对你使用的是哪些感兴趣?请限制包装函数的答案- 即不超过几行代码.
你知道,我们可以将lambda函数包装或存储到std::function:
#include <iostream>
#include <functional>
int main()
{
std::function<float (float, float)> add = [](float a, float b)
// ^^^^^^^^^^^^^^^^^^^^
{
return a + b;
};
std::cout << add(1, 2) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是std::function,你可以看到它是一个模板类,但它可以接受任何类型的函数签名.
例如,float (float, float)在这种形式return_value (first_arg, second_arg).
std::function它的结构是什么以及如何接受函数签名x(y,z)以及如何使用它?是float (float, float)C++中一个新的有效表达式?
我正在创建一个存储有关特定数据源的元数据的类.元数据以树形结构,与XML的结构非常相似.元数据值可以是整数,小数或字符串值.
我很好奇C++是否有一种很好的方法来存储这种情况的变体数据.我希望变体使用标准库,所以我避免使用可用的COM,Ole和SQL VARIANT类型.
我目前的解决方案看起来像这样:
enum MetaValueType
{
MetaChar,
MetaString,
MetaShort,
MetaInt,
MetaFloat,
MetaDouble
};
union MetaUnion
{
char cValue;
short sValue;
int iValue;
float fValue;
double dValue;
};
class MetaValue
{
...
private:
MetaValueType ValueType;
std::string StringValue;
MetaUnion VariantValue;
};
Run Code Online (Sandbox Code Playgroud)
MetaValue类具有各种Get函数,用于获取当前存储的变量值,但它最终使每个查询值成为if/else if语句的一大块,以确定我正在寻找的值.
我还探讨了将值存储为只有一个字符串,并执行转换以获得不同的变体类型,但据我所见,这会导致一堆内部字符串解析和错误处理,这不是很好,打开浮点值的精度和数据丢失问题很大,如果上面说的问题,仍然不会消除查询if/else.
是否有人使用标准库实现或看到了更清晰的用于C++变体数据类型的东西?
我想用以下方式创建一个lambda:
auto l1 = condition ?
[](){ return true; } :
[number](){ return number == 123; };
Run Code Online (Sandbox Code Playgroud)
但是,我收到了错误:
operands to ?: have different types ‘main()::<lambda()>’ and ‘main()::<lambda()>’
Run Code Online (Sandbox Code Playgroud)
显然,类型似乎是相同的.我想,number只捕获一个lambdas可能是一个问题,但我得到了同样的错误:
//check if capturing number in both lambdas would help
auto l2 = condition ?
[number](){ return true; } :
[number](){ return number == 123; };
//maybe the first lambda capture was optimised out? let's make sure:
auto l3 = condition ?
[number](){ return number != 123; } :
[number](){ return …Run Code Online (Sandbox Code Playgroud) 我想知道是否unordered_map使用类型擦除实现,因为unordered_map<Key, A*>并且unordered_map<Key, B*>可以使用完全相同的代码(除了强制转换,这是机器代码中的无操作).也就是说,两者的实现可以基于unordered_map<Key, void*>保存代码大小.
更新:此技术通常被称为精简模板成语(感谢下面的评论者指出这一点).
更新2:我对Howard Hinnant的观点特别感兴趣.我希望他读到这个.
所以我写了这个小测试:
#include <iostream>
#if BOOST
# include <boost/unordered_map.hpp>
using boost::unordered_map;
#else
# include <unordered_map>
using std::unordered_map;
#endif
struct A { A(int x) : x(x) {} int x; };
struct B { B(int x) : x(x) {} int x; };
int main()
{
#if SMALL
unordered_map<std::string, void*> ma, mb;
#else
unordered_map<std::string, A*> ma;
unordered_map<std::string, B*> mb;
#endif
ma["foo"] = new …Run Code Online (Sandbox Code Playgroud) 如果我使用诸如的模板定义类
template<class K, class V>
class myclass {
...
};
Run Code Online (Sandbox Code Playgroud)
有没有办法将myclass定义的对象传递给函数而不使用函数的模板?换句话说,对于每个接受myclass对象的函数,是否还需要使用模板<class K,class V>来定义?
这样做的主要原因是我想定义一组作用于myclass对象的静态函数,这样我就可以在cpp文件中而不是在头文件中限制这些函数的范围.
所以我正在读这篇关于类型擦除的文章.但该文章中的代码似乎部分不正确,例如:
template <typename T>
class AnimalWrapper : public MyAnimal
{
const T &m_animal;
public:
AnimalWrapper(const T &animal)
: m_animal(animal)
{ }
const char *see() const { return m_animal.see(); }
const char *say() const { return m_animal.say(); }
};
Run Code Online (Sandbox Code Playgroud)
其次是
void pullTheString()
{
MyAnimal *animals[] =
{
new AnimalWrapper(Cow()), /* oO , isn't template argument missing? */
....
};
}
Run Code Online (Sandbox Code Playgroud)
这些错误使我不鼓励在文章中进一步阅读.
无论如何; 有没有人可以用简单的例子教C++中哪种类型的擦除?
我想了解它是如何std::function工作的,但无法理解它.
在GMan的回答中,restore_base类的析构函数不是virtual,所以我一直想知道它是如何工作的.通常restorer_base,在对象超出范围之后,您只希望执行析构函数,但似乎restorer_holder真正调用了派生的析构函数.有人关心开导我吗?