标签: template-meta-programming

为什么C++模板使用尖括号语法?

标题问题是指在1990年左右引入模板的C++标准中的设计决策.

为什么设计师使用<>(尖括号)而不是()(圆括号)?这样做可以节省大量程序员与位移相关的错误

std::vector<std::vector<int>> // does not work until C++11
Run Code Online (Sandbox Code Playgroud)

只在C++ 11中得到修复.我没有看到引入额外语法的理由,可以说,圆括号在保持变化极简主义的同时可以起到同样的作用.你可以使用它

template(typename T) // Define template if round brackets could be used
mytemplate { ... }
...
...
mytemplate(mytemplate(int)) obj; //Instantiate template when round brackets could be used
Run Code Online (Sandbox Code Playgroud)

精通C++历史的人能否挖掘出使用尖括号的原始设计理念?或者,你能说明为什么其他解决方案也不会有效吗?

c++ language-design template-meta-programming c++11

41
推荐指数
1
解决办法
5738
查看次数

通过引用重载多个函数对象

在C++ 17中,实现一个overload(fs...)函数是很容易的,在fs...满足任意数量的参数的情况下FunctionObject,它返回一个行为类似于重载的新函数对象fs....例:

template <typename... Ts>
struct overloader : Ts...
{
    template <typename... TArgs>
    overloader(TArgs&&... xs) : Ts{forward<TArgs>(xs)}...
    {
    }

    using Ts::operator()...;
};

template <typename... Ts>
auto overload(Ts&&... xs)
{
    return overloader<decay_t<Ts>...>{forward<Ts>(xs)...};
}

int main()
{
    auto o = overload([](char){ cout << "CHAR"; }, 
                      [](int) { cout << "INT";  });

    o('a'); // prints "CHAR"
    o(0);   // prints "INT"
}
Run Code Online (Sandbox Code Playgroud)

wandbox上的实例


由于上面的overloader继承Ts...,它需要复制或移动函数对象才能工作.我想要一些提供相同重载行为的东西,但只引用传递的函数对象.

我们称之为假设函数ref_overload(fs...).我的尝试正在使用std::reference_wrapper …

c++ overloading function-object template-meta-programming c++17

39
推荐指数
2
解决办法
1786
查看次数

未评估上下文中的默认模板参数和lambda:错误或功能?

我们考虑使用完全相同的语法创建两种不同类型的目标。这可以通过lambdas轻松完成:

auto x = []{};
auto y = []{};
static_assert(!std::is_same_v<decltype(x), decltype(y)>);
Run Code Online (Sandbox Code Playgroud)

但是,我们正在寻找另一种更优雅的语法,而不是使用lambda。这是一些测试。我们首先定义一些工具:

#include <iostream>
#include <type_traits>
#define macro object<decltype([]{})>
#define singleton object<decltype([]{})>

constexpr auto function() noexcept
{
    return []{};
}

template <class T = decltype([]{})>
constexpr auto defaulted(T arg = {}) noexcept
{
    return arg;
}

template <class T = decltype([]{})>
struct object
{
    constexpr object() noexcept {}
};

template <class T>
struct ctad
{
    template <class... Args>
    constexpr ctad(const Args&...) noexcept {}
};

template <class... Args>
ctad(const Args&...) -> …
Run Code Online (Sandbox Code Playgroud)

c++ lambda language-lawyer template-meta-programming c++20

39
推荐指数
1
解决办法
758
查看次数

检查 C++ 成员是否为私有的机制

我正在为本科生编写单元测试,并希望将某些成员强制为公共或私有成员。我知道实际测试私有成员的方法,例如,#define private public或使用朋友类,但没有看到任何可以让我准确检查成员是否为私有的方法。

蛮力方法将尝试编译并解析输出错误,例如,寻找类似的东西error: 'foo' is a private member of 'Bar',但我希望有人会有更好的技巧!

c++ unit-testing private-members template-meta-programming

38
推荐指数
3
解决办法
3472
查看次数

检查是否存在C++成员函数,可能受到保护

我正在尝试检测一个类是否具有特定的功能(具体来说shared_from_this(),是继承自哪个std::enable_shared_from_this<Some Unknown Class>).为了使事情变得更复杂,我需要知道它是否具有此功能,即使它已从远程基类继承或使用受保护访问继承.

我已经查看了其他问题,例如这个问题,但提供的方法不适用于检测受保护的成员函数.

我目前使用的方法如下:

template <class T>
struct shared_from_this_wrapper : public T
{
  template <class U>
  static auto check( U const & t ) -> decltype( t.shared_from_this(), std::true_type() );

  static auto check( ... ) -> decltype( std::false_type() );
};

template<class T>
struct has_shared_from_this : decltype(shared_from_this_wrapper<T>::check(std::declval<shared_from_this_wrapper<T>>()))
{ };
Run Code Online (Sandbox Code Playgroud)

我当前解决方案的缺陷是它不适用于声明的类final.所以我正在寻找一个满足以下成员函数的测试解决方案:

  1. 适用于声明的类 final
  2. 使用受保护的成员函数
  3. 适用于继承
  4. 不需要知道函数的返回类型
  5. 在gcc,clang和MSVC 2013下编译(最后一个可能限制过于花哨的SFINAE)

编辑:我有一个可行的解决方案,但需要与帮助类成为朋友,这也不是一个理想的解决方案,但现在可能是一种解决方法(因为它满足所有要求):

struct access
{
  template <class T>
  static auto shared_from_this( T const & t ) -> …
Run Code Online (Sandbox Code Playgroud)

c++ final sfinae template-meta-programming c++11

35
推荐指数
1
解决办法
2587
查看次数

为什么标准不允许在模板参数列表中初始化常量依赖类型?

在这篇文章的答案" (部分)专门化依赖类型的非类型模板参数 "中,它指出:

与专用非类型参数对应的模板参数的类型不应取决于特化的参数.[例如:

template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error

template< int X, int (*array_ptr)[X] > class A {};
int array[5];
template< int X > class A<X,&array> { }; // error
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

我的问题是为什么这个限制在这里?至少有一个用例,我发现这个限制干扰了编写干净的代码.例如

template <typename T, T*>
struct test;

template <typename T>
struct test<T, nullptr> // or struct test<T, (T*)nullptr>
{
};

template <typename R, typename...ARGs, R(*fn)(ARGs...)>
struct test<R(ARGs...), fn>
{
};
Run Code Online (Sandbox Code Playgroud)

虽然我不确定是否还有其他案例表明基于类型的常量是一个超出没有任何意义的问题.

任何人都有理由说明为何如此?

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

34
推荐指数
1
解决办法
1179
查看次数

有没有人在现实生活中使用模板元编程?

我在五年多前发现了模板元编程,并且在阅读现代C++设计方面获得了巨大的成功,但我从未发现在现实生活中使用它的机会.

曾经使用在实际代码这种技术?

Boost的贡献者无需申请; o)

c++ templates template-meta-programming

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

如何检测类型是否可以流式传输到std :: ostream?

我正在尝试编写一个类型特征来检测一个类型是否重载了适合用于输出流的operator <<().

我错过了一些东西,因为我总是认为一个简单的空类没有操作符.

这里的代码:

template<typename S, typename T>
class is_streamable
{
    template<typename SS, typename TT>
    static auto test(SS&& s, TT&& t)
    -> decltype(std::forward<SS>(s) << std::forward<TT>(t));

    struct dummy_t {};
    static dummy_t test(...);

    using return_type = decltype(test(std::declval<S>(), std::declval<T>()));

public:
    static const bool value = !std::is_same<return_type, dummy_t>::value;
};

class C {};

int main() {
    std::cout << is_streamable<std::stringstream, C>::value << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

1
Run Code Online (Sandbox Code Playgroud)

这是在ideone:https://ideone.com/ikSBoT

我究竟做错了什么?

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

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

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

介绍

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

玩具线性层次

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

试图代码

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
查看次数

模板元编程

有人可以向我解释一下,为什么第一个模板元编程方式将进入无限循环,而第二个模板正确运行。

#include <iostream>
using namespace std;

template<int N, int M>
struct commondivs {                                              
  static const int val = (N<M) ? commondivs<N,(M-N)>::val : commondivs<(N-M),M>::val;
};

template<int N>
struct commondivs<N,N> {
  static const int val = N;
};


int commondiv(int N, int M){
    if(N==M){
        return N;
    }   
    return (N<M)?commondiv(N,(M-N)):commondiv((N-M),M);     
}

int main() {

    cout << commondivs<9,6>::val << endl;
    cout << commondiv(9,6) << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ templates template-meta-programming

29
推荐指数
3
解决办法
2401
查看次数