小编Que*_*tin的帖子

为什么C++ STL基于模板如此重要?(而不是*接口*)

我的意思是,除了它的义务名称(标准模板库)......

C++最初的目的是将OOP概念呈现给C.即:您可以基于其类和类层次结构来判断特定实体可以做什么和不可行(不管它是如何做的).由于多重继承的问题,以及C++以某种笨拙的方式支持接口的概念(与java等相比),某些能力组合更难以这种方式描述,但它存在(并且可能是改善).

然后模板与STL一起发挥作用.STL似乎采用了经典的OOP概念,并使用模板代替了它们.

在使用模板来概括类型的情况之间应该有区别,其中类型自身与模板的操作无关(例如,容器).有一个vector<int>完美的感觉.

但是,在许多其他情况下(迭代器和算法),模板化类型应该遵循"概念"(输入迭代器,前向迭代器等等),其中概念的实际细节完全由模板的实现定义函数/类,而不是与模板一起使用的类的类,这是对OOP的一种反对使用.

例如,您可以告诉函数:

void MyFunc(ForwardIterator<...> *I);
Run Code Online (Sandbox Code Playgroud)

更新:由于在原始问题中不清楚,因此ForwardIterator可以自行模板化以允许任何ForwardIterator类型.相反,将ForwardIterator作为一个概念.

只需通过查看其定义来预期转发迭代器,您需要查看实现或文档:

template <typename Type> void MyFunc(Type *I);
Run Code Online (Sandbox Code Playgroud)

我可以支持使用模板的两个声明:通过为每个使用的类型定制编译模板,而不是使用vtable,可以提高编译代码的效率.并且模板可以与本机类型一起使用.

但是,我正在寻找一个更为深刻的理由,为什么放弃传统的OOP而不是模仿STL呢?(假设你读到那么远:P)

c++ oop templates stl

210
推荐指数
9
解决办法
3万
查看次数

JQuery字符串包含check

我需要检查一个字符串是否包含另一个字符串?

var str1 = "ABCDEFGHIJKLMNOP";
var str2 = "DEFG";
Run Code Online (Sandbox Code Playgroud)

我用哪个函数来确定str1是否包含str2?

javascript string comparison jquery contains

93
推荐指数
5
解决办法
39万
查看次数

条件运算符的返回类型和两阶段查找

请考虑以下代码段:

struct Base { };
struct Derived : Base { };

void f(Base &) { std::cout << "f(Base&)\n"; }

template <class T = int>
void g() {
    Derived d;
    f(T{} ? d : d); // 1
}

void f(Derived &) { std::cout << "f(Derived&)\n"; }

int main() {
    g();
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我认为应该在第一阶段查找对fat 的函数调用// 1,因为它的参数的类型是明确的Derived&,因此可以解析为f(Base&)范围中唯一的一个.

Clang 3.8.0同意我的观点,但是GCC 6.1.0没有,并推迟f到第二阶段的查找,在那里f(Derived&)被选中.

哪个编译器是对的?

c++ dependent-name language-lawyer compiler-bug name-lookup

39
推荐指数
2
解决办法
1085
查看次数

结交模板模板参数

我有一个带有模板模板参数的类模板,我想将此参数(即其所有特化)声明为friend.但我找不到正确的语法.

template <template <class> class T>
struct Foo {

    template <class U>
    friend T;           // "C++ requires a type specifier for all declarations"

    template <class U>
    friend struct T;    // "declaration of 'T' shadows template parameter"

    template <class U>
    friend struct T<U>; // "cannot specialize a template template parameter"

    pretty<please>
    lets(be) friends T; // Compiler shook its standard output in pity
};
Run Code Online (Sandbox Code Playgroud)

如何将模板模板参数声明为friend

Coliru片段

c++ templates friend template-templates

29
推荐指数
1
解决办法
648
查看次数

通过make_unique/make_shared调用initializer_list构造函数

我试图用来std::make_unique实现一个构造函数要接收的类std::initializer_list.这是一个最小的案例:

#include <string>
#include <vector>
#include <initializer_list>
#include <memory>

struct Foo {
    Foo(std::initializer_list<std::string> strings) : strings(strings) {}

    std::vector<std::string> strings;
};

int main(int, char**) {

    auto ptr = std::make_unique<Foo>({"Hello", "World"});

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

您可以在Coliru上看到它没有构建:

main.cpp:14:56: error: no matching function for call to 'make_unique(<brace-enclosed initializer list>)'
     auto ptr = std::make_unique<Foo>({"Hello", "World"});
Run Code Online (Sandbox Code Playgroud)

那么,make_unique据说无法使用initializer_lists?GCC 4.9.1中有错误吗?或者我忽略了什么?

c++ initializer-list unique-ptr c++14

27
推荐指数
2
解决办法
9451
查看次数

什么是C语言中的"宽字符串"?

我在书中遇到过这个:

wscanf(L"%lf", &variable);
Run Code Online (Sandbox Code Playgroud)

其中第一个参数的类型为wchar_t *.

scanf("%lf", &variable);与第一个参数的类型不同char *.

那有什么不同呢?我之前从未听过"宽字符串".我听过一些名为Raw String Literals的东西,它正在打印字符串(不需要像转义序列那样的东西),但那不是在C.

c string widechar

25
推荐指数
2
解决办法
4万
查看次数

VLA和操作数大小的副作用

我知道sizeof永远不会评估它的操作数,除非在所述操作数是VLA的特定情况下.或者,我以为我知道.

void g(int n) {
    printf("g(%d)\n", n);
}

int main(void) {
    int i = 12;

    char arr[i]; // VLA

    (void)sizeof *(g(1), &arr); // Prints "g(1)"
    (void)sizeof (g(2), arr);   // Prints nothing

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

到底是怎么回事?

以防万一,这是在Coliru上用GCC 5.1编译的.

c side-effects sizeof variable-length-array

20
推荐指数
1
解决办法
326
查看次数

为什么这个ADL案例有效?

怎么find_type知道功能typemap在哪里?
它收到的参数不是来自该命名空间,而是来自std命名空间!

#include <type_traits>
#include <memory>

namespace lib {
    template<typename T>
    struct find_type {
        using type = decltype(typemap(std::declval<T>()));
    };
}

namespace test {
    struct Test {};
    auto typemap(std::unique_ptr<Test>) -> int;    
}

static_assert(std::is_same<int, lib::find_type<std::unique_ptr<test::Test>>::type>::value, "");
Run Code Online (Sandbox Code Playgroud)

这段代码怎么样?允许这个的规则是什么?

我用GCC 6.3和clang 3.9.1测试了它.

c++ language-lawyer argument-dependent-lookup c++11

19
推荐指数
2
解决办法
1214
查看次数

使用GCC和clang __attribute __((cleanup))和指针声明的一种好的惯用方法

我认为GCC扩展__attribute__((cleanup))是一个好主意,至少在某些情况下,但我无法弄清楚如何以一种好的方式使用它.我所做的一切看起来仍然很烦人.

我看到了很多的代码做#define _cleanup_(x) __attribute__((cleanup(x))只是为了少打字,但它有没有办法通过有没有一个标准功能一样free或者closedir,fclose等?

我看到我不能写:

__attribute__((cleanup(free))) char *foo = malloc(10);
Run Code Online (Sandbox Code Playgroud)

因为清理回调会收到char**指针,所以我必须总是这样写:

static void free_char(char **ptr) { free(*ptr); }
__cleanup__((free_char)) char *foo = malloc(10);
Run Code Online (Sandbox Code Playgroud)

这非常烦人,最烦人的部分是为你需要的所有类型定义这样的清理函数,因为显然你不能只为它定义它void **.避免这些事情的最佳方法是什么?

c gcc clang

18
推荐指数
2
解决办法
3518
查看次数

右移和有符号整数

在我的编译器上,以下伪代码(用二进制替换的值):

sint32 word = (10000000 00000000 00000000 00000000);
word >>= 16;
Run Code Online (Sandbox Code Playgroud)

生成一个如下所示word的位域:

(11111111 11111111 10000000 00000000)
Run Code Online (Sandbox Code Playgroud)

我的问题是,我可以依赖所有平台和C++编译器的这种行为吗?

c++ bit-shift platform-specific

17
推荐指数
4
解决办法
2万
查看次数