相关疑难解决方法(0)

如何在使用Clang编译CRTP Singleton时修复声称缺少"显式实例化声明"?

我们正在使用奇怪的重复模板模式来实现单例.但是,在最近的Clang版本中,我们得到了一个-Wundefined-var-template警告.建议的修复是添加"显式实例化声明".

我试图这样做,但后来我在编译单元中获得了"实例化后显式特化"的错误,其中单例模板类成员变量的定义是.

解决此警告突出显示的问题的适当构造是什么?


简化细节(已删除大部分逻辑,以制作MCVE):

SingletonBase.hh:

template < class T > class SingletonBase {
public:
  static T * get_instance() {
    if ( ! instance_ ) {
      instance_ = T::create_singleton_instance();
    }
    return instance_;
  }
private:
  static T * instance_;
};
Run Code Online (Sandbox Code Playgroud)

Singleton.hh:

#include "SingletonBase.hh"

class Singleton : public SingletonBase< Singleton > {
  friend class SingletonBase< Singleton >;
public:
  int do_stuff(int v) { return v+2; }
private:
  static Singleton * create_singleton_instance() {
    return new Singleton;
  }
};
Run Code Online (Sandbox Code Playgroud)

Singleton.cc:

#include "Singleton.hh"
template …
Run Code Online (Sandbox Code Playgroud)

c++ singleton crtp c++11 clang++

6
推荐指数
2
解决办法
3629
查看次数

调用派生类的模板函数

我在C++中遇到问题,在调用派生类的函数的同时有一个指向基类的指针.

编辑:一些答案提到我CRTP

但我的观点是我需要一个指向"Base*"类而不是"Base*"的指针,因为我不知道当前正在处理的类型(当前实例是从某种工厂创建的).

类别:

class Base 
{
..
template<typename T>
func (T arg) { ... };
};

class Derived1 : public Base
{
...
template<typename T>
func (T arg) { ... };
};


class Derived1 : public Base
{
...
template<typename T>
func (T arg) { ... };
};
Run Code Online (Sandbox Code Playgroud)

用法:

int main()
{
   Base* BasePtr = new Derived1();

   // The expected function to be called is Derived1::func<int>()
   BasePtr->func<int>();

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

我不能使func虚拟,因为该语言不支持虚拟模板功能.

仅当类只有模板参数时才允许,但如果其中的函数具有模板参数则不允许.

我已经看到在Boost.Serialization中解决了类似的问题,但无法理解解决方案.

谢谢,

Koby Meir

c++ templates derived boost-serialization

5
推荐指数
2
解决办法
4884
查看次数

如何从专门用于自身的模板派生类?

我真的不知道如何描述这个,但这是代码:

class A : public std::vector<A>
{
};

//....

A a;
a.push_back(a);
Run Code Online (Sandbox Code Playgroud)

它做了什么,为什么要这样做?

c++ templates

5
推荐指数
1
解决办法
173
查看次数

CRTP的静态多态性:使用基类调用派生方法

virtualC ++ 的主要优点之一是能够使用基类(指针或引用)来调用派生方法。

我正在阅读使用CRTP实现静态多态性的知识,但是我不明白如何使用该技术实现上面提到的内容,因为Base当需要模板时,我无法将函数声明为采用类型。

在我看来,仅通过使用函数重载就可以实现本文中描述的内容,因此,我敢肯定,该技术必须有更多的功能。

(PS:在回答该问题的评论中提到了这个确切的问题,但不幸的是没有人回答:“ vtables真正提供的功能是使用基类(指针或引用)来调用派生方法。您应该在此处显示如何使用CRTP进行操作。”)

这是我的最小代码,它给出错误“在'&'令牌无效Print(Base&Object)之前缺少模板参数”。

#include <cstring>
#include <iostream>

template <typename Derived>
struct Base
{
    std::string ToStringInterface() { return static_cast<Derived*>(this)->ToString(); }

    std::string ToString()  {   return "This is Base.";     }
};

struct Derived : Base<Derived>
{
    std::string ToString()  {   return "This is Derived.";  }
};

void Print(Base& Object)
{
    std::cout << Object->ToStringInterface() << std::endl;
}

int main()
{
    Derived MyDerived;

    // This works, but could have been achieved with a function …
Run Code Online (Sandbox Code Playgroud)

c++ polymorphism templates crtp

5
推荐指数
2
解决办法
3710
查看次数

使用 CRTP 实现单例

阅读此答案后,我尝试实现一些简单的 CRTP 用法。我想我会尝试实现 Singleton(是的,我知道 - 这只是为了练习和研究)模式,因为链接的答案已经做到了这一点......除了它无法编译的事实。

引用的代码如下:

template <class ActualClass> 
class Singleton
{
   public:
     static ActualClass& GetInstance()
     {
       if(p == nullptr)
         p = new ActualClass;
       return *p; 
     }

   protected:
     static ActualClass* p;
   private:
     Singleton(){}
     Singleton(Singleton const &);
     Singleton& operator = (Singleton const &); 
};
template <class T>
T* Singleton<T>::p = nullptr;

class A: public Singleton<A>
{
    //Rest of functionality for class A
};
Run Code Online (Sandbox Code Playgroud)

然后我将其“现代化”为:

template <class T>
class Singleton {
public:
    Singleton()                              = delete;
    Singleton(const Singleton&) …
Run Code Online (Sandbox Code Playgroud)

c++ singleton crtp

5
推荐指数
1
解决办法
2864
查看次数

我是否更喜欢使用mixins或函数模板向一组不相关的类型添加行为?

Mixins和函数模板是为多种类型提供行为的两种不同方式,只要这些类型满足某些要求即可.

例如,假设我想编写一些允许我将对象保存到文件的代码,只要这个对象提供了一个toString成员函数(这是一个相当愚蠢的例子,但请耐心等待).第一种解决方案是编写如下函数模板:

template <typename T>
void toFile(T const & obj, std::string const & filename)
{
    std::ofstream file(filename);
    file << obj.toString() << '\n';
}
...
SomeClass o1;
toFile(o1, "foo.txt");
SomeOtherType o2;
toFile(o2, "bar.txt");
Run Code Online (Sandbox Code Playgroud)

另一个解决方案是使用CRTP使用mixin :

template <typename Derived>
struct ToFile
{
    void toFile(std::string const & filename) const
    {
        Derived * that = static_cast<Derived const *>(this);
        std::ofstream file(filename);
        file << that->toString() << '\n';
    }
};

struct SomeClass : public ToFile<SomeClass>
{
    void toString() const {...}
};
...
SomeClass …
Run Code Online (Sandbox Code Playgroud)

c++ oop templates mixins

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

如何继承成员函数,以便始终返回对派生实例的引用?

我正在开发一个迭代器系列,其中所有迭代器类X都有X& operator++() {++x; return *this}共同点,因此将它放在一个公共基类中似乎是个好主意.不幸的是,返回类型会发生变化,因为它应该始终返回对派生类的引用.

以下说明了这个问题.我想f()工作,但唯一的解决方法我能想出是g()h(),这是不令人满意的:

struct A {
    A& f() {return *this;}

    template <typename T>
    T& g() {return *(T*)this;}

    template <typename T>
    T& h(T& unused) {return *(T*)this;}
};

struct B : A {
    int x;
    B(int x) : x(x) {}
};

int main() {
    B b(12);

    //B b1 = b.f();   // error: conversion from 'A' to non-scalar type 'B' requested

    B b2 = b.g<B>();  // works
    B b3 = …
Run Code Online (Sandbox Code Playgroud)

c++ polymorphism inheritance templates c++11

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

警告:X 的默认移动赋值运算符将多次移动赋值虚拟基类 Y

在 C++11 下测试库时,我在 Clang 下收到警告。我以前从未遇到过警告,搜索并没有提供太多的阅读和研究方式。

警告如下所示,它似乎与多重继承和公共基类有关。但我不清楚触发警告的细节或我应该做些什么来解决它。

我的第一个问题是,这是一个需要解决的问题吗?还是仅仅是效率问题?

我的第二个问题是(如果需要),如何解决警告?或者有哪些可用于修复它的选项?


以下是一些附加信息:

  • 编译器:Apple LLVM version 6.0 (clang-600.0.57)(基于LLVM 3.5svn)
  • g++ -DDEBUG -g2 -O2 -std=c++11 -fPIC -march=native -pipe -c test.cpp

还在 Stack Overflow 上回顾了以下内容,但我不清楚它们在哪里相交:

Crypto++也大量使用Curiously Recurring Template Pattern进行编译时多态性。


头文件可在线获取,这里是实际警告:

g++ -DDEBUG -g2 -O2 -std=c++11  -Wno-deprecated-declarations -fPIC -march=native -pipe -c rsa.cpp
In file included from rsa.cpp:4:
In file included from ./rsa.h:12:
./pubkey.h:635:26: warning: defaulted move assignment operator of 'InvertibleRSAFunction' will move assign …
Run Code Online (Sandbox Code Playgroud)

c++ multiple-inheritance move-semantics c++11

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

如何有效地重用专门的模板结构中的代码?

我正在为数学库创建自己的向量结构。

目前,我会创建类似于这样的结构:

template <unsigned int size, typename T>
struct vector {
    // array of elements
    T elements[size];

    // ...
};
Run Code Online (Sandbox Code Playgroud)

然而,数学库的主要用例将导致主要使用 2 维、3 维和 4 维向量(通常为vec2vec3vec4)。因此,一个有用的功能是能够在可能的情况下从向量访问 x、y、z 和 w 值。然而,这也存在一些问题。

x、和成员需要是、等的引用变量。这意味着,如果向量的元素少于 4 个,则某些引用将不会被初始化yzwelements[0]elements[1]

当然,这可以通过专门的模板来实现,这就是我目前正在做的:

template <unsigned int size, typename T>
struct vector {
    // ...
}

template <typename T>
struct vector<2, T> {
    // same as with before, except with references to X and …
Run Code Online (Sandbox Code Playgroud)

c++ templates

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

在派生函数中指定 void* 参数

我想做一些在 Cpp 中可能无法实现的事情,但我找不到专门针对此的帖子。

我想让派生类指定虚函数上的 void* 参数的类型。

我有一个名为 interface 的基类,带有一个发送函数。

// pure virtual
class Interface{
    virtual bool Send(const void*)=0;

};

struct Packet{
    DataType data;
};

class SpecificInterface{
     bool Send(const DataType*);
}
Run Code Online (Sandbox Code Playgroud)

有没有办法让这样的工作?意图是SpecificInterface::Send 实现Interface::Send。允许特定接口不是纯虚拟的,同时将 void* 限制为特定的数据包类型。

否则我知道我可以使用 void* 参数并将其 static_cast 转换为 Packet* 类型;但是,我不希望其他人发送无法转换为 Packet* 的指针类型。

如果这不清楚,请告诉我

c++ inheritance void-pointers

2
推荐指数
1
解决办法
83
查看次数