小编gex*_*ide的帖子

C#如何允许C++不允许虚拟模板方法的虚拟泛型方法?

C++不支持虚拟模板方法.原因在于,vtable无论何时进行这种方法的新实例化(必须将其添加到vtable),这都会改变.

相比之下,Java确实允许虚拟通用方法.在这里,还清楚如何实现:Java泛型在运行时被擦除,因此泛型方法是运行时的常用方法,因此不需要对其进行更改vtable.

但现在到C#.C#确实有具体的泛型.使用具体化的泛型,特别是当使用值类型作为类型参数时,必须有不同版本的泛型方法.但是后来我们遇到了与C++相同的问题:每当进行泛型方法的新实例化时,我们都需要改变vtable.

我对C#的内部工作并不是太深入,所以我的直觉可能完全是错误的.那些对C#/ .NET有更深入了解的人能告诉我他们如何在C#中实现通用虚拟方法吗?

这是代码,以显示我的意思:

[MethodImpl(MethodImplOptions.NoInlining)]
static void Test_GenericVCall()
{
    var b = GetA();
    b.M<string>();
    b.M<int>();
}

[MethodImpl(MethodImplOptions.NoInlining)]
static A GetA()
{
    return new B();
}

class A
{
    public virtual void M<T>()
    {
    }
}

class B : A
{
    public override void M<T>()
    {
        base.M<T>();
        Console.WriteLine(typeof(T).Name);
    }
}
Run Code Online (Sandbox Code Playgroud)

在调用M函数时,CLR如何调度到正确的JITed代码Test_GenericVCall

c# c++ generics templates generic-method

29
推荐指数
4
解决办法
2909
查看次数

使用std :: ostream打印可变参数包的最简单方法是什么?

使用逗号分隔的参数包的最简单方法是什么std::ostream

例:

template<typename... Args>
void doPrint(std::ostream& out, Args... args){
   out << args...; // WRONG! What to write here?
}

// Usage:
int main(){
   doPrint(std::cout,34,"bla",15); // Should print: 34,bla,15
}
Run Code Online (Sandbox Code Playgroud)

注意:可以假设<<操作员的相应过载可用于所有类型的参数包.

c++ templates variadic-templates c++11

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

从Java生成LLVM代码

我想使用Java的LLVM代码生成框架.

也就是说,我希望Java代码编译成LLVM.我只想要一个用于代码生成的LLVM库,我可以从Java调用它.通常的LLVM库是C,所以我不能使用它.

有没有Java端口?如果不是,那么最简单的方法是什么呢?将API包装到JNI中?

java code-generation llvm

19
推荐指数
3
解决办法
1万
查看次数

为什么std :: string_view在三元表达式中创建悬空视图?

考虑std::string_view从返回a 的方法const std::string&或从空字符串返回的方法。令我惊讶的是,以这种方式编写方法会导致悬空的字符串视图:

const std::string& otherMethod();

std::string_view myMethod(bool bla) {
    return bla ? otherMethod() : ""; // Dangling view!
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/1Hu_p2

似乎编译器首先将std::string结果的临时副本otherMethod()放在堆栈上,然后返回此临时副本的视图,而不是仅返回引用的视图。首先,我想到了一个comipler错误,但是G ++和clang都这样做。

修复很容易:将其包装otherMethod为一个显式结构即可string_view解决此问题:

std::string_view myMethod(bool bla) {
    return bla ? std::string_view(otherMethod()) : ""; // Works as intended!
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/Q-sEkr

为什么会这样呢?为什么原始代码会在没有警告的情况下创建隐式副本?

c++ language-lawyer dangling-pointer string-view c++17

19
推荐指数
1
解决办法
639
查看次数

关于模板结构大小的静态断言

我需要确保模板结构与其成员的大小完全相同.static_assert似乎是这里的首选工具.但是,我不能static_assert在结构本身内部使用,因为那里的大小还不知道.这是我想要的:

template<typename T1,typename T2>
struct foo {
    T1 v1;
    T2 v2;
    // Doesn't compile, invalid application of sizeof to incomplete type
    static_assert(sizeof(foo<T1,T2>)==sizeof(T1)+sizeof(T2),"Struct size invalid");
};
Run Code Online (Sandbox Code Playgroud)

这不起作用.那怎么办呢?我不想让实例化模板的人在每个实例化中检查自己.只要实例化结构,检查应该是完全自动的.

c++ templates sizeof static-assert

18
推荐指数
3
解决办法
1204
查看次数

如何发信号通知测试想跳过自己

我在谷歌测试中有一组打字的测试用例.但是,其中一些测试用例根本不适用于特定类型参数.考虑这个示例类型测试用例:

TYPED_TEST_P(TheTest, ATest){
    if(TypeParam::isUnsuitedForThisTest()){
        return;
    }
    // ... real test code goes here
}
Run Code Online (Sandbox Code Playgroud)

这很好用,简单地跳过测试.但是,在执行测试时,我看到了平常

[ RUN      ] XYZ/TheTest/0.ATest
[       OK ] XYZ/TheTest/0.ATest (0 ms) 
Run Code Online (Sandbox Code Playgroud)

因此,测试被忽略并不明显,看起来它只是成功了.我想以某种方式显示测试用例被跳过.谷歌测试中是否有某种方法可以表示跳过了测试用例.像这样的东西(这不存在):

TYPED_TEST_P(TheTest, ATest){
    if(TypeParam::isUnsuitedForThisTest()){
        SIGNAL_SKIPPED(); // This is what I would like to have
        return;
    }
    // ... real test code goes here
}
Run Code Online (Sandbox Code Playgroud)

然后,输出将更改为如下所示:

[ RUN      ] XYZ/TheTest/0.ATest
[  SKIPPED ] XYZ/TheTest/0.ATest (0 ms)
Run Code Online (Sandbox Code Playgroud)

gtest中是否有一个能够实现这种行为的功能?

c++ googletest

14
推荐指数
1
解决办法
2118
查看次数

boost :: any/std :: any是否存在就地的小对象?

要保存任意大的对象,boost::any/ std::any当然需要为对象分配堆空间.但是,对于大小小于或等于指针(int,char,bool,...)的小类型,any可以将值存储在指针槽或其他一些就地内存中,而不是分配堆空间.但实施是否这样做?

我有一个场景,我经常将小型类型存储在一个any只有strings 类型的大型类型中.代码非常热,因此我在问这个问题.如果没有执行优化,我可能会更好地使用自己的实现来存储小型类型.

c++ boost c++17

14
推荐指数
2
解决办法
2065
查看次数

使用ZipFileSystem压缩一个巨大的文件夹会导致OutOfMemoryError

java.nio包具有一种处理zip文件的漂亮方式,将它们视为文件系统.这使我们能够像普通文件一样处理zip文件内容.因此,只需使用Files.copy将所有文件复制到zip文件中即可实现压缩整个文件夹.由于子文件夹也要复制,我们需要一个访问者:

 private static class CopyFileVisitor extends SimpleFileVisitor<Path> {
    private final Path targetPath;
    private Path sourcePath = null;
    public CopyFileVisitor(Path targetPath) {
        this.targetPath = targetPath;
    }

    @Override
    public FileVisitResult preVisitDirectory(final Path dir,
    final BasicFileAttributes attrs) throws IOException {
        if (sourcePath == null) {
            sourcePath = dir;
        } else {
        Files.createDirectories(targetPath.resolve(sourcePath
                    .relativize(dir).toString()));
        }
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(final Path file,
    final BasicFileAttributes attrs) throws IOException {
    Files.copy(file,
        targetPath.resolve(sourcePath.relativize(file).toString()), StandardCopyOption.REPLACE_EXISTING);
    return FileVisitResult.CONTINUE;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的"复制目录递归"访问者.它用于递归复制目录.但是,ZipFileSystem使用它,我们也可以使用它将目录复制到zip文件中,如下所示: …

java zip nio

13
推荐指数
1
解决办法
3592
查看次数

C++ 11:安全双重检查锁定以进行延迟初始化.可能?

考虑到线程安全的双重检查锁定(对于单例或懒惰初始化),我已经阅读了很多问题.在某些线程中,答案是模式完全被破坏,其他人提出了解决方案.

所以我的问题是:有没有办法在C++中编写一个完全线程安全的双重检查锁定模式?如果是这样,它看起来如何.

我们可以假设C++ 11,如果这让事情变得更容易.据我所知,C++ 11改进了内存模型,可以产生所需的改进.

我知道通过使用双重检查保护变量volatile可以在Java中实现.由于C++ 11从Java中借用了大部分内存模型,所以我认为它有可能,但是如何?

c++ thread-safety double-checked-locking c++11

12
推荐指数
1
解决办法
4733
查看次数

在静态变量初始化中使用cout时的C++分段错误

我有一个程序,我使用cout发出调试信息.代码在静态全局变量的初始化中执行,即在程序执行的早期.当我使用自己的构建脚本来构建程序时,它首次使用cout时会出现段错误(只有字符串文字被转移到cout中,所以它不能是值).我使用valgrind检查早期写入无效位置,但没有(并且也没有可能生成这些写入的代码,我在输出之前不做太多).当我将源代码复制到eclipse项目并让eclipse内置构建器构建它时,一切正常.我没有使用简单编译的奇怪的构建器设置-ggdb -std=c++0x,这些是唯一的两个标志.

那么,如果之前没有无效的写入,那么带有字符串文字段错误的cout可能是什么原因?构建配置如何影响这个?

(对不起,我不能给你一个最小的例子,因为这个例子可以简单地在你的机器上编译,就像在使用eclipse构建器时那样)

编辑:这是堆栈跟踪:

0x00007ffff7b6d7d1 in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib   /x86_64-linux-gnu/libstdc++.so.6
(gdb) backtrace
#0  0x00007ffff7b6d7d1 in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00007ffff7b6dee9 in std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2  0x00007ffff7b6e2ef in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) ()
  from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00000000004021be inTest::fill (this=0x6120f8, funcs=...) at inTest.cpp:92
Run Code Online (Sandbox Code Playgroud)

最后一帧是我的代码.第92行简单地写道:

std::cout << "Test";
Run Code Online (Sandbox Code Playgroud)

c++ cout initialization segmentation-fault

12
推荐指数
2
解决办法
4607
查看次数