小编Hap*_*tus的帖子

使用演绎的C++可变扩展

我正在开发一个处理非类型C函数(SQLite)的库,我想强力输入它.

我们的想法是拥有一个FieldDef强类型,允许用户将原始类型(如int,double和std :: string)绑定到弱db类型.我的问题是库的语义很重,我想添加一些自动类型推导.

所以我有一堆"基本类型":

namespace FieldType {
  struct Integer { using rawtype = int; };
  struct Real{ using rawtype = double; };
  struct Text{ using rawtype = std::string; };
  struct Blob{ using rawtype = std::vector<uint8_t>; };
}
Run Code Online (Sandbox Code Playgroud)

我还有一个insert和一个query函数,允许插入和查询表而不使用SQL语句.查询将是纯选择.无论如何.预期用途是:

FieldDef<FieldType::Integer> mId = makeFieldDef("id", FieldType::Integer()).primaryKey().autoincrement();
FieldDef<FieldType::Text> mName = makeFieldDef("name", FieldType::Text());
FieldDef<FieldType::Integer> mValue = makeFieldDef("value", FieldType::Integer());

SQLiteTable::insert(std::make_tuple(mName, mValue), std::make_tuple(record.name, record.value));

std::vector<Record> r;
SQLiteTable::query
            (std::make_tuple(mName, mValue), [&r](std::tuple<std::string, int> res) {
        r.push_back(Record{std::get<0>(res), std::get<1>(res)});
});
Run Code Online (Sandbox Code Playgroud)

我用这种方式实现了插入:

template <typename ...Ts, …
Run Code Online (Sandbox Code Playgroud)

c++ variadic-templates c++11 c++14

7
推荐指数
1
解决办法
243
查看次数

在C++ 11中处理模板化函数中的void变量

我有一个模板类,必须在调用参数和返回类型为泛型的函数之前执行某些操作.

这是方法:

template <typename ReturnType, typename ...Args>
ReturnType function (Args ...args) {
  // prepare for call
  // ...
  ReturnType rv = makeCall(args...);  // [1]
  // dismiss the call
  // ...
  return rv;
}
Run Code Online (Sandbox Code Playgroud)

当然,如果ReturnType没有正确编译它void.当我在这种情况下使用它时:

function<void>(firstArg, secondArg);
Run Code Online (Sandbox Code Playgroud)

编译器响应

error: return-statement with a value, in function returning 'void' [-fpermissive]

指向标有[1]的行.

除了传递-fpermissive给编译器之外还有其他解决方案吗?我宁愿有一个独特的方法,因为我发现可能的解决方案是使用enable_if和实例化不同的版本is_same.

先感谢您.

- 更新 -

这是一个完整的例子.我应该说我们的函数确实是类方法.

#include <type_traits>
#include <iostream>

class Caller {
public:
    Caller() {}

    template <typename ReturnType, typename ...Arguments>
    ReturnType …
Run Code Online (Sandbox Code Playgroud)

c++ templates variadic c++11

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

MSVC 19删除继承的构造函数

在MSVC 19.16下,如果类B明确地从类A继承构造函数,并且还定义了自己的构造函数,则忽略继承的构造函数.

class A {
public:
    A() {}
    A(int x) {}
};

class B : public A {
public:
    using A::A;

    B(double x) : A() {}
};

int main()
{
    B b;                 // error C2512: 'B': no appropriate default constructor available
                         // note: see declaration of 'B'
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在gcc下正确编译.任何人都知道它是编译器错误,还是我想念的东西?谢谢.

c++ visual-c++ c++11

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

使用C ++元编程构建静态字符串

我正在编写一个开源的sqlite接口库(例如mSqliteCpp),该库使用c ++类和类型正确管理sqlite数据库。

到目前为止,该库大量使用TMP来构建SQL字符串,但是我发现了一个可能以某种方式影响库效率的问题。

我正在使用类来管理字段定义,类定义,查询和语句。基本上是定义一个表或一条SELECT语句,首先使用适当的FieldDef<T>对象定义字段,然后将它们传递给一个语句构建器,该构建器返回格式正确的SQL语句。

例如:

auto fldId = sqlite::makeFieldDef("id", sqlite::FieldType::Integer());
auto fldName = sqlite::makeFieldDef("name", sqlite::FieldType::Text());
auto fldValue = sqlite::makeFieldDef("value", sqlite::FieldType::Real());

sqlite::statements::Select select("Table", fldId, fldName, fldValue);

ASSERT_EQ(select.string(), "SELECT id,name,value FROM Table;");
Run Code Online (Sandbox Code Playgroud)

请注意,每个字段都是FieldType通过传递给makeFieldDef函数的类型强类型化的,但是可以交换具有相似类型的不同字段。因此,ASSERT调用中的SQL语句是在运行时生成的。

我希望至少在某些条件下在编译时构建它们。例如,开发人员可以使用其他类或constexpr关键字。但是目前我不知道是否可以实现。

有哪些可能的模式?是否可以通过TMP静态构建字符串?我正在使用C ++ 11/14。

谢谢。

c++ template-meta-programming c++11

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