标签: variadic-templates

如何防止可变参数构造函数优先于复制构造函数?

我有一个模板'Foo',它拥有一个T,我希望它有一个可变参数构造函数,将它的参数转发给T的构造函数:

template<typename T>
struct Foo {

    Foo()
        : t() {}

    Foo(const Foo& other)
        : t(other.t) {}

    template<typename ...Args>
    Foo(Args&&... args)
        : t(std::forward<Args>(args)...) {}

    T t;
};
Run Code Online (Sandbox Code Playgroud)

但是,这会导致Foo无法复制:

int main(int argc, char* argv[]) {
    Foo<std::shared_ptr<int>> x(new int(42));
    decltype(x) copy_of_x(x);  // FAILS TO COMPILE
    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

因为,根据这个答案,参数的非常量导致可变参数构造函数更好地匹配.出于显而易见的原因,我不想强​​制我的调用者使用const_cast.

我找到的一个可能的解决方案是为Foo编写一个"复制构造函数",它采用非const Foo并使用构造函数转发:

Foo(Foo& other)
    : Foo(const_cast<const Foo&>(other)) {}
Run Code Online (Sandbox Code Playgroud)

当定义了这个构造函数时,事情再次起作用:现在首选非const Foo参数copy ctor.然而,这对我来说似乎非常粗略,因为这种"治愈"似乎比疾病更糟糕.

是否有另一种方法来实现这种效果,表明自然拷贝构造函数应该优先于可变参数构造函数?如果没有,定义这个非const参数复制构造函数会有什么不利后果吗?

c++ copy-constructor variadic-templates c++11

33
推荐指数
1
解决办法
2504
查看次数

在C++中混淆模板17 std :: visit的例子

std::visit()在cppreference中查看页面时,https: //en.cppreference.com/w/cpp/utility/variant/visit, 我遇到了我无法理解的代码......

这是缩写版本:

#include <iomanip>
#include <iostream>
#include <string>
#include <type_traits>
#include <variant>
#include <vector>

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...)->overloaded<Ts...>;

int main() {
    std::vector<std::variant<int,long,double,std::string>> vec = { 10, 15l, 1.5, "hello" };
    for (auto& v : vec) {
        std::visit(overloaded{
            [](auto arg) { std::cout << arg << ' '; },
            [](double arg) { std::cout << std::fixed << arg << ' '; },
            [](const std::string& arg) { std::cout << std::quoted(arg) << …
Run Code Online (Sandbox Code Playgroud)

c++ lambda variadic-templates generic-lambda c++17

33
推荐指数
2
解决办法
2168
查看次数

如何在可变参数模板函数中使用source_location?

C ++ 20功能std::source_location用于捕获有关调用函数的上下文的信息。当我尝试将其与可变参数模板函数一起使用时,遇到一个问题:我看不到放置source_location参数的地方。

以下操作无效,因为可变参数必须在末尾:

// doesn't work
template <typename... Args>
void debug(Args&&... args,
           const std::source_location& loc = std::source_location::current());
Run Code Online (Sandbox Code Playgroud)

以下内容也不起作用,因为调用者将被介于两者之间的参数所困扰:

// doesn't work either, because ...
template <typename... Args>
void debug(const std::source_location& loc = std::source_location::current(),
           Args&&... args);

// the caller will get confused
debug(42); // error: cannot convert 42 to std::source_location
Run Code Online (Sandbox Code Playgroud)

可以在可变参数模板中无缝使用的评论中告诉我std::source_location,但是我很难弄清楚该如何做。如何std::source_location与可变参数模板函数一起使用?

c++ default-arguments variadic-templates c++20 std-source-location

33
推荐指数
4
解决办法
937
查看次数

如何反转可变参数模板函数的参数顺序?

我有一个带有varargs模板参数模板函数,就像这样

template<typename Args...>
void ascendingPrint(Args... args) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

我想写

template<typename Args...>
void descendingPrint(Args... args) {
  /* implementation using ascendingPrint()? */
}
Run Code Online (Sandbox Code Playgroud)

如何在传递参数包之前反转参数包 的顺序args,即在伪代码中:

template<typename Args...>
void descendingPrint(Args... args) {
  ascendingPrint( reverse(args) );
}
Run Code Online (Sandbox Code Playgroud)

c++ templates variadic-functions variadic-templates c++11

32
推荐指数
5
解决办法
7028
查看次数

六个点在可变参数模板中意味着什么?

以下是来自libstdc ++的一些部分特化:std::is_function<type_traits>

  /// is_function
  template<typename>
    struct is_function
    : public false_type { };

  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes...)>
    : public true_type { };

  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes...) &>
    : public true_type { };

  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes...) &&>
    : public true_type { };

  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes......)>
    : public true_type { };

  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes......) &>
    : public true_type { };

  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes......) …
Run Code Online (Sandbox Code Playgroud)

c++ templates partial-specialization variadic-templates c++11

32
推荐指数
0
解决办法
1781
查看次数

如何在可变参数模板类中获取函数指针的参数类型?

这是这个问题的后续问题:具有任何参数列表的函数的泛型函子

我有这个仿函数类(完整代码见上面的链接):

template<typename... ARGS>
class Foo
{
    std::function<void(ARGS...)> m_f;
  public:
    Foo( std::function<void(ARGS...)> f ) : m_f(f) {}
    void operator()(ARGS... args) const { m_f(args...); }
};
Run Code Online (Sandbox Code Playgroud)

在operator()中,我可以使用递归的"剥离"功能轻松访问args ...如http://www2.research.att.com/~bs/C++0xFAQ.html#variadic-templates

我的问题是:我想在构造函数中访问f的参数类型,即ARGS ....显然我无法访问值,因为到目前为止还没有,但参数类型列表以某种方式埋没在f中,不是吗?

c++ function-pointers functor variadic-templates c++11

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

使用C++ 11可变参数模板在编译时快速排序

我刚刚通过使用C++ 11可变参数模板在编译时对其进行评估来实现快速排序算法.但是,当数据集太大时,我遇到性能问题.

#include <iostream>

using namespace std;

template<int... vs>
struct Seq
{}; 
template<int v1, int...vs>
struct Seq<v1, vs...>{
};


template<typename newT, typename srcT>
struct PushFront{
};
template<int vadded, int...vs>
struct PushFront<Seq<vadded>, Seq<vs...>>{
  typedef Seq<vadded, vs...> ResultType;
};

template<typename T>
struct PopFront{
};
template<int v1, int...vs>
struct PopFront<Seq<v1, vs...>>{
  typedef Seq<vs...> RemaindType;
  typedef Seq<v1>    ResultType;
};

template<typename T1, typename T2>
struct CatSeq{};
template<int...v, int...us>
struct CatSeq<Seq<v...>, Seq<us...>>{
  typedef Seq< v..., us... >  ResultType;
};


template<bool c, typename NewT, typename TrueClsT, typename …
Run Code Online (Sandbox Code Playgroud)

c++ metaprogramming quicksort variadic-templates c++11

30
推荐指数
2
解决办法
3126
查看次数

获取第N种可变参数模板模板?

如何获取第N种可变参数模板模板?例如

template<typename... Args>
class MyClass
{
    Args[0] mA; // This is wrong. How to get the type?

};
Run Code Online (Sandbox Code Playgroud)

c++ variadic-templates

30
推荐指数
2
解决办法
6690
查看次数

使用模板元编程的更好的LOG()宏

典型的基于LOG()宏的日志记录解决方案可能如下所示:

#define LOG(msg) \
    std::cout << __FILE__ << "(" << __LINE__ << "): " << msg << std::endl 
Run Code Online (Sandbox Code Playgroud)

这允许程序员使用方便且类型安全的流操作符创建数据丰富的消息:

string file = "blah.txt";
int error = 123;
...
LOG("Read failed: " << file << " (" << error << ")");

// Outputs:
// test.cpp(5): Read failed: blah.txt (123)
Run Code Online (Sandbox Code Playgroud)

问题是这会导致编译器内联多个ostream :: operator <<调用.这会增加生成的代码,从而增加函数大小,我怀疑这可能会损害指令缓存性能并阻碍编译器优化代码的能力.

这是一个"简单"替代方案,它通过调用可变参数模板函数替换内联代码:

********* 解决方案#2:VARIADIC模板功能 *********

#define LOG(...) LogWrapper(__FILE__, __LINE__, __VA_ARGS__)

// Log_Recursive wrapper that creates the ostringstream
template<typename... Args>
void LogWrapper(const char* file, int line, const Args&... …
Run Code Online (Sandbox Code Playgroud)

c++ logging variadic-templates variadic-macros c++11

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

类型线性谱系中最低的共同祖先

介绍

让我们假设我们有一个类似于以下类型线性层次结构:

玩具线性层次

然后我想要的是一种机制,从该谱系中的任意数量的类型返回最低共同祖先.

试图代码

template<typename...Ts>
struct LCA;

template<typename T1, typename T2, typename...Ts>
struct LCA<T1, T2, Ts...>
{
    using base = typename std::conditional
    <
        std::is_base_of<T1, T2>::value, T1,
        typename std::conditional <
            std::is_base_of<T2, T1>::value, T2, void
        >::type
    >::type;

    using type = typename LCA<base, Ts...>::type;
};

template<typename T>
struct LCA<T>
{
    using type = T;
};
Run Code Online (Sandbox Code Playgroud)

现场演示

用例

我的用例是相当典型的:在制作一些iterator工具时我想提取"限制性最强"的迭代器类型,因此迭代器中存在(种类)线性层次结构,我应该能够根据需要提升层次结构:

LCA<Bidirectional, RandomAccess, RandomAccess> -> Bidirectional
LCA<RandomAccess, Input, Forward>              -> Input
Run Code Online (Sandbox Code Playgroud)

问题

  1. 是否有更简洁/惯用的方法来处理错误情况,其中两个或更多类型是层次结构的陌生人?目前的方法是返回void …

c++ templates template-meta-programming variadic-templates c++11

30
推荐指数
2
解决办法
797
查看次数