我正在尝试用模板和SFINAE制作一些东西,我是初学者.我浪费了大量的时间来完成最简单的工作.你能帮我理解它的工作原理吗?
C <T,Ts ...>的构造函数采用T参数,该参数是A <U>或B <U>,但在这两种情况下具有不同的行为.我无法告诉你我试图这么做的一切.这对我来说似乎是最不愚蠢的.
template<typename T> class A{
public: A(){} };
template<typename T> class B{
public: B(){} };
template<typename T> struct enable_if_A {};
template<typename T> struct enable_if_A< A<T> > {typedef A<T> type;};
template<typename T> struct enable_if_B {};
template<typename T> struct enable_if_B< B<T> > {typedef B<T> type;};
template<typename T,typename... Ts> class C{
public:
C(typename enable_if_A<T>::type const &p){cout << "A" << endl;}
C(typename enable_if_B<T>::type const &p){cout << "B" << endl;}
};
// ...
A<float> a;
B<float> b;
C<A<float> > ca(a); …Run Code Online (Sandbox Code Playgroud) 这是我想要使用的代码的一个简短示例:
template <class T>
class B
{
public :
bool func1(const T& t)
{
// do something
}
};
class A
{
B<int*> b;
public:
void func2(const int* a)
{
b.func1(a);
}
};
Run Code Online (Sandbox Code Playgroud)
我收到这个错误:
错误C2664:'B :: func1':无法将参数1从'const int*'转换为'int*const&'
是一种解决这个问题的方法,而无需更改函数声明和不使用const_cast?
编辑:
问题背后的一些信息
B 实际上是我写的容器类(比如列表)
A 是使用该列表的类
func1 是一个需要查找元素是否在列表中的函数
func2 是一个接收要从列表中删除的元素的函数
好的,所以我有这个模板类,有点像单向列表。
template <typename T> List
Run Code Online (Sandbox Code Playgroud)
它具有此内部功能打印
public:
void Print();
Run Code Online (Sandbox Code Playgroud)
如您所料,它从头到尾打印列表内容;但是,由于模板可以将类视为T,因此可以想象,在这种情况下,我将需要Print()的不同实现。例如,我有另一个班级Point
class Point{
private:
int x, y;
public:
int getX();
int getY();
}
Run Code Online (Sandbox Code Playgroud)
所以我要专门为积分设计打印。我尝试了这个:
void List<Point>::Print();
Run Code Online (Sandbox Code Playgroud)
但是编译器告诉我
prototype for void List<Point> Print() doesn match any in class List<Point>
Run Code Online (Sandbox Code Playgroud)
虽然
candidates are: from List<T> [with T = Point] void List<Point>::Print()
Run Code Online (Sandbox Code Playgroud)
对我来说,这似乎是一样的功能。怎么了?以及如何编写T特定的模板类函数?
在构建期间,编译器会不断分配不兼容的类型。
错误信息:
error: assigning to 'int' from incompatible type 'QString'
typeduserproperty.cpp:115:28: note: in instantiation of member function 'core::TypedUserProperty<int>::setValue' requested here
Run Code Online (Sandbox Code Playgroud)
样例代码
/**
* @brief setValue
* set value to property
* @param val
* value to set to property
* @return
* true - successfully set value
* false - invalid value
*/
template<class T>
void TypedUserProperty<T>::setValue(QVariant val)
{
if (std::is_same<T, int>::value == true)
{
this->_value = val.toInt();
}
else if (std::is_same<T, QString>::value == true)
{
this->_value = val.toString();
} …Run Code Online (Sandbox Code Playgroud) c++ templates if-statement function-templates template-classes
有两个模板类A和B.如何强制它们被实例化为相同类型而不与另一个嵌套?例如,如果我定义这两个类如下:
template <class T>
class A {};
template <class T>
class B {};
Run Code Online (Sandbox Code Playgroud)
那么有可能的是,用户可以做这样的事A<int> a;,并B<float> b;
我想强制A和B具有完全相同的类型,但我不希望它们彼此嵌套.所以当有人使用这两个类时,A和B必须具有相同的类型.有没有办法做到这一点?那些像这样设计课程的好习惯是什么?
谢谢
我试着理解enable_if实现,这是一对模板类.我不明白,为什么enable_if<true, int>不匹配第一个?这是怎么决定的?
#include <iostream>
template <bool, class T = void>
struct enable_if
{
enable_if() { std::cout << "invalid type";}
};
template <class T>
struct enable_if<true, T>
{
typedef T type;
enable_if() { std::cout <<"valid type";}
};
int main(){
enable_if<0==0, int> example; // print "valid type"
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我有一个可序列化的模板类:
可序列化.h
#pragma once
#ifndef SERIALIZABLE_H
#define SERIALIZABLE_H
#include "Logger.h"
#include <string>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception_ptr.hpp>
template<class T>
class Serializable {
public:
static bool Deserialize(Serializable<T>* object, std::string serializedObject) {
try {
return object->SetValuesFromPropertyTree(GetPropertyTreeFromJsonString(serialized));
} catch (...) {
std::string message = boost::current_exception_diagnostic_information();
Logger::PostLogMessageSimple(LogMessage::ERROR, message);
std::cerr << message << std::endl;
}
}
private:
static boost::property_tree::ptree GetPropertyTreeFromJsonString(const std::string & jsonStr) {
std::istringstream iss(jsonStr);
boost::property_tree::ptree pt;
boost::property_tree::read_json(iss, pt);
return pt;
}
}
#endif // SERIALIZABLE_H
Run Code Online (Sandbox Code Playgroud)
但问题是 Logger 类使用了一个继承自 …
我正在学习模板化类的非模板友元函数和模板友元函数。所以我尝试了下面的代码:
#include <iostream>
template<typename T>
class cl
{
private :
T val;
public:
cl()= default;
explicit cl(T v) : val(std::move(v)) {}
friend void non_template_friend(cl m);
};
template <typename T>
void non_template_friend(cl<T> m) { std::cout << m.val << std::endl;}
int main()
{
cl<int> c(10);
non_template_friend(c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
因此,当我编译时,我得到了:undefined reference tonon_template_friend(cl)' ` 所以要解决这个问题,我必须像这样在类定义中移动友元函数定义:
template<typename T>
class cl
{
private :
T val;
public:
cl()= default;
explicit cl(T v) : val(std::move(v)) {}
friend void non_template_friend(cl m) { std::cout << m.val …Run Code Online (Sandbox Code Playgroud) 我正在浏览一些代码,我发现了这样的事情:
class GarbageCollectorProcess : public process::Process<GarbageCollectorProcess>
Run Code Online (Sandbox Code Playgroud)
我想知道这是否有效.如果是,那么这不应该导致某种自定义循环,因为我们使用另一个依赖于GarbageCollectorProcess定义的类来定义GarbageCollectorProcess吗?
我正在努力重新创建前向链表类,以便我可以更好地理解指针。我遇到了障碍,我有一个名为forward_list 的模板类。在这个类的私有部分中,我有另一个类,我希望它具有与主(外部)类相同的类型,这个类称为节点。
\n#ifndef FORWARD_LIST_HPP\n#define FORWARD_LIST_HPP\n\ntemplate <class T>\nclass forward_list\n{\n private:\n class node\n {\n T data;\n node<T>* next;\n };\n node<T>* head, tail;\n public:\n forward_list();\n ~forward_list();\n void pushBack(T t);\n void print();\n};\n\n#endif\nRun Code Online (Sandbox Code Playgroud)\n当我将上面的代码与其余代码一起编译时,会产生以下错误:
\n./forward_list.hpp:11:19: error: non-template type \xe2\x80\x98node\xe2\x80\x99 used as a template\n 11 | node<T>* next;\n | \nRun Code Online (Sandbox Code Playgroud)\n我也尝试过这个(我会在我添加的行上添加一个“*”。)
\n./forward_list.hpp:11:19: error: non-template type \xe2\x80\x98node\xe2\x80\x99 used as a template\n 11 | node<T>* next;\n | \nRun Code Online (Sandbox Code Playgroud)\n这是此更改产生的错误:
\n./forward_list.hpp:8:19: error: declaration of template parameter \xe2\x80\x98T\xe2\x80\x99 shadows template parameter\n 8 | …Run Code Online (Sandbox Code Playgroud) 当我发现这种依赖于预处理器的创建模板类的方式时,我只是搞乱了:
#include <iostream>
#include <typeinfo>
// Is this a valid template class?
#define TEMPLATE_CLASS(T)\
class TemplateClass_ ## T\
{\
private:\
T value;\
public:\
void print_type()\
{\
std::cout << typeid(T).name() << std::endl;\
}\
}
class Sample {};
TEMPLATE_CLASS(int) obj1;
TEMPLATE_CLASS(char) obj2;
TEMPLATE_CLASS(Sample) obj3;
int main(int argc, char* argv[])
{
obj1.print_type();
obj2.print_type();
obj3.print_type();
}
Run Code Online (Sandbox Code Playgroud)
我简单地编译了这个:
g++ src.cpp -o main.exe
Run Code Online (Sandbox Code Playgroud)
输出:
i
c
6Sample
Run Code Online (Sandbox Code Playgroud)
现在,正如您所看到的,它几乎与模板类的工作方式相同.除了明显的事实之外,对象只能全局声明,因为它实际上在您使用时定义了一个新的内联类TEMPLATE_CLASS(T),并且无法在函数中定义新类.解决方案可以是:
TEMPLATE_CLASS(float);
int main() { TemplateClass_float obj; }
Run Code Online (Sandbox Code Playgroud)
无论如何,这给了我很多思考.首先,这甚至可以被称为有效的泛型类吗?那么,是否可以使用它而不是标准模板功能?显然,使用标准模板功能要方便得多,但我的意思是说,这个工作也一样吗?最后,C++标准内部定义的模板功能是否与我在预处理器上做的类似?如果没有,这个实现和C++的标准模板功能有什么区别?
我编写了以下使用成员指针函数的类:
#include <stdlib.h>
#include <vector>
template<class Type>
class PrimitiveAccessor {
public :
PrimitiveAccessor(
JNIEnv* env, const char name[], const char ctorSig[],
Type (JNIEnv::*callTypeMethodFunction) (jobject, jmethodID)
) {
this->env = env;
this->type = (jclass)env->NewGlobalRef(env->FindClass(name));
this->callTypeMethodFunction = callTypeMethodFunction;
}
~PrimitiveAccessor(){
env->DeleteGlobalRef(this->type);
}
private:
JNIEnv* env;
jclass type;
jmethodID constructorId;
jmethodID callTypeMethodId;
Type (JNIEnv::*callTypeMethodFunction) (jobject, jmethodID);
};
class Environment {
public:
Environment(JNIEnv* env) {
this->env = env;
this->init();
}
~Environment(){
this->env = 0;
delete(this->jintAccessor);
this->jintAccessor = 0;
}
private:
JNIEnv* env;
PrimitiveAccessor<jint>* jintAccessor; …Run Code Online (Sandbox Code Playgroud) 我在C++中为链表创建了一个Node类:
template <class T> class Node {
public:
T val;
Node* next;
Node(T val) {
this->val = val;
this->next = nullptr;
}
~Node() {
Node<T>* temp = this->next;
if (temp != nullptr && temp->next != nullptr)
delete(temp->next);
}
};
Run Code Online (Sandbox Code Playgroud)
在尝试tp初始化时:
definition:
Node<Device>* devices;
code (in function):
this->devices = new Node<Device>({ this->serial_counter, name });
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
错误C2512'设备':没有合适的默认构造函数健身房c:\ users\amitm\onedrive \מסמכים\ visual studio 2015\projects\gym\gym \node.h 7
第7行:
Node(T val) {
Run Code Online (Sandbox Code Playgroud)
此外,如果需要,这是"设备"构造函数:
Device::Device(int id, char* name) {
this->id = id;
strcpy(this->name, name);
}
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个错误?我在网上看了一个多小时,找不到适合我的解决方案.
c++ ×13
template-classes ×13
templates ×8
c++11 ×3
class ×2
const ×1
const-cast ×1
constructor ×1
if-statement ×1
inheritance ×1
pointers ×1
sfinae ×1
visual-c++ ×1