标签: template-meta-programming

检查成员是否存在,可能在基类C++ 11版本中

/sf/answers/137702841/中,提供了一种解决方案,用于静态检查成员是否存在,可能在类型的子类中:

template <typename Type> 
class has_resize_method
{ 
   class yes { char m;}; 
   class no { yes m[2];}; 
   struct BaseMixin 
   { 
     void resize(int){} 
   }; 
   struct Base : public Type, public BaseMixin {}; 
   template <typename T, T t>  class Helper{}; 
   template <typename U> 
   static no deduce(U*, Helper<void (BaseMixin::*)(), &U::foo>* = 0); 
   static yes deduce(...); 
public: 
   static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0))); 
};
Run Code Online (Sandbox Code Playgroud)

但是,它不适用于C++ 11 final类,因为它继承了被测试的类,这会final阻止它.

OTOH,这一个:

template <typename C>
struct has_reserve_method {
private:
    struct No …
Run Code Online (Sandbox Code Playgroud)

c++ final type-traits template-meta-programming c++11

29
推荐指数
2
解决办法
9104
查看次数

在编译时使整数序列唯一

假设我有:

template<int... N>
class seq
{
};

template<int... N>
struct uniq{
    using type = seq<N...>;
};
Run Code Online (Sandbox Code Playgroud)

我需要以某种方式使序列唯一,以便

std::is_same_v<uniq<1,2,2,2,3,3,3>::type, seq<1, 2, 3>>; 
Run Code Online (Sandbox Code Playgroud)

最终是真的。换句话说,使序列唯一,然后创建一个 seq。
有没有办法在编译时实现这一点?

c++ templates template-meta-programming c++17

29
推荐指数
2
解决办法
1461
查看次数

每个可变参数模板参数生成一个类成员

我有一个模板类,其中每个模板参数代表内部计算可以处理的一种类型的值.需要模板(而不是函数重载),因为值作为boost :: any传递,并且它们的类型在运行时之前不清楚.

为了正确地转换为正确的类型,我想为每个可变参数类型都有一个成员列表,如下所示:

template<typename ...AcceptedTypes> // e.g. MyClass<T1, T2>
class MyClass {
    std::vector<T1> m_argumentsOfType1;
    std::vector<T2> m_argumentsOfType2; // ...
};
Run Code Online (Sandbox Code Playgroud)

或者,我想将模板参数类型存储在列表中,以便用它做一些RTTI魔术(?).但是如何将它们保存在std :: initializer_list成员中对我来说也不清楚.

谢谢你的帮助!

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

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

元编程:函数定义失败定义了一个单独的函数

这个答案中,我根据类型的is_arithmetic属性定义了一个模板:

template<typename T> enable_if_t<is_arithmetic<T>::value, string> stringify(T t){
    return to_string(t);
}
template<typename T> enable_if_t<!is_arithmetic<T>::value, string> stringify(T t){
    return static_cast<ostringstream&>(ostringstream() << t).str();
}
Run Code Online (Sandbox Code Playgroud)

dyp建议,不是is_arithmetic类型的属性,是否to_string为类型定义是模板选择标准.这显然是可取的,但我不知道如何说:

如果std::to_string未定义,则使用ostringstream重载.

声明to_string标准很简单:

template<typename T> decltype(to_string(T{})) stringify(T t){
    return to_string(t);
}
Run Code Online (Sandbox Code Playgroud)

这与我无法弄清楚如何构建的标准相反.这显然不起作用,但希望它传达了我正在尝试构建的内容:

template<typename T> enable_if_t<!decltype(to_string(T{})::value, string> (T t){
    return static_cast<ostringstream&>(ostringstream() << t).str();
}
Run Code Online (Sandbox Code Playgroud)

c++ templates result-of sfinae template-meta-programming

26
推荐指数
4
解决办法
2030
查看次数

在编译时用C++生成随机数

我正在尝试random在编译时使用C++ 11的库预先计算随机值.我主要是按照例子.我在这做错了什么?

using namespace std;
#include <iostream>
#include <vector>
#include <random>

vector<double> rands;
typedef std::mt19937_64 RNG;
uint64_t seed_val;
RNG rng; 

void initialize() {
     rng.seed(seed_val);
}

constexpr vector<double> generate_random( )                 //size_t numbers)
{   
    int numbers = 1000;
    std::uniform_real_distribution<double> zero_one(0.0, 1.0);
        for (unsigned int i = 0; i < numbers; i++) { 
             double rand_num = zero_one(rng);
             rands.push_back( rand_num );
    }
    return rands;
}

int main()
{
    cout << "TMP rands";
    for_each( rands.begin(), rands.end(), [] (double value)
    {
        cout<<value<<endl;
    });
} …
Run Code Online (Sandbox Code Playgroud)

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

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

如何在编译时检查两种类型是否相同(如果它与Boost强类型定义一起使用,则为奖励积分)

我想知道是否有可能在编译时检查两种类型是否相同.我想出的是(idk如果它有效,因为它感觉hackish和IDK标准好,所以IDK在测试时要寻找什么).

#include <boost/strong_typedef.hpp>
BOOST_STRONG_TYPEDEF(double, cm);
BOOST_STRONG_TYPEDEF(double, inch);
template<typename T, typename U>
static constexpr void __help() 
{
}
template<typename T, typename U>
class AreSameType
{
    public:
    constexpr operator bool()
    {
     return &__help<T,U> == &__help<U,T>;
    };
};
Run Code Online (Sandbox Code Playgroud)

用法:

int main()
{
        static_assert(AreSameType<double,float>()== false, "oh noes1");
        static_assert(AreSameType<double,double>()== true, "oh noes2");
        static_assert(AreSameType<int*,double*>()== false, "oh noes3");
        static_assert(AreSameType<double*,double>()== false, "oh noes4");
        static_assert(AreSameType<const double,double>()== false, "oh noes5");
        static_assert(AreSameType<inch,cm>()== true, "oh expected"); //fires
}
Run Code Online (Sandbox Code Playgroud)

所以

1)有更好的方法吗?
2)这个功能黑客的地址保证按标准工作(我打赌不会:))?

c++ static-assert template-meta-programming constexpr c++11

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

gcc和clang上都有奇怪的嵌套类部分特化结果

在编写一个供个人使用的小模板元编程库时,我遇到了一个有趣的问题.

由于我正在为一些元函数重用一些部分特化,我决定将它们放在一个公共模板类下,并使用标签和嵌套的部分特化来提供行为上的差异.

问题是我得到了荒谬(对我而言)的结果.这是一个最小的例子,展示了我想要做的事情:

#include <iostream>
#include <cxxabi.h>
#include <typeinfo>

template <typename T>
const char * type_name()
{
    return abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
}

template <typename... Args>
struct vargs {};

namespace details   
{
    template <typename K>
    struct outer
    {
        template <typename Arg>
        struct inner
        {
            using result = Arg;
        };
    };
}

struct tag {};

namespace details
{
    template <>
    template <typename Arg, typename... Args>
    struct outer<tag>::inner<vargs<Arg, Args...>>
    {
        using result = typename outer<tag>::inner<Arg>::result;
    };
}

template <typename T>
using test_t …
Run Code Online (Sandbox Code Playgroud)

c++ templates language-lawyer template-meta-programming c++11

24
推荐指数
1
解决办法
899
查看次数

在现代C++中优雅地定义多维数组

使用T[][][]语法定义多维数组很容易.但是,这会创建一个原始数组类型,它不适合现代C++.这就是我们std::array从C++ 11开始的原因.但是使用多维数组来定义多维数组的语法std::array非常混乱.例如,要定义三维int数组,您必须编写std::array<std::array<std::array<int, 5>, 5>, 5>.语法根本不可扩展.我要求解决这个问题.也许,使用C++提供的现有实用程序无法修复此问题.在这种情况下,我很高兴开发了一种自定义工具来简化语法.

自己找到了解决方案:

template <typename T, std::size_t n, std::size_t... ns>
struct multi_array {
  using type = std::array<typename multi_array<T, ns...>::type, n>;
};

template <typename T, std::size_t n>
struct multi_array<T, n> {
  using type = std::array<T, n>;
};

template <typename T, std::size_t... ns>
using multi_array_t = typename multi_array<T, ns...>::type;
Run Code Online (Sandbox Code Playgroud)

想知道是否可以进一步简化实施.

c++ arrays multidimensional-array template-meta-programming c++14

24
推荐指数
1
解决办法
4228
查看次数

如何检查模板参数是否可以使用给定签名进行调用

基本上,我想要实现的是编译时验证(可能很好的错误消息)注册可调用(函数,lambda,带调用运算符的结构)具有正确的签名.示例(static_assert要填写的内容):

struct A {
  using Signature = void(int, double);

  template <typename Callable>
  void Register(Callable &&callable) {
    static_assert(/* ... */);
    callback = callable;
  }

  std::function<Signature> callback;
};
Run Code Online (Sandbox Code Playgroud)

c++ templates template-meta-programming c++11 callable-object

24
推荐指数
3
解决办法
2882
查看次数

为什么C++ 11类型特征不是别名模板?

类似的问题:为什么type_traits用专门的模板结构而不是constexpr实现? - 但答案不同.

我意识到别名模板不能专门化,因此目前无法直接用于实现类型特征1.然而,这是委员会的一个有意识的决定,据我所知,没有技术理由禁止这样做.

那么将类型特征实现为别名模板,简化它们的语法会不会更有意义?

考虑

 typename enable_if<is_pointer<T>::value, size_t>::type
 address(T p);
Run Code Online (Sandbox Code Playgroud)

 enable_if<is_pointer<T>, size_t> address(T p);
Run Code Online (Sandbox Code Playgroud)

当然,这从Boost.TypeTraits移动时引入了一个突破性的界面变化- 但这真的是一个大问题吗?

毕竟,无论如何都需要修改代码,因为类型驻留在不同的命名空间中,并且由于许多现代C++程序员不愿意打开命名空间,因此将明确限定(如果它将被更改).

另一方面,它极大地简化了代码.鉴于模板元编程经常被深深嵌套,复杂和复杂,显然更清晰的界面是有益的.

我错过了什么吗?如果没有,我会欣赏一个不仅仅是猜测的答案,而是依赖(并且可以引用)对委员会决策理由的了解.


1间接非常好!考虑:

template <typename T> using is_pointer = typename meta::is_pointer<T>::type;
Run Code Online (Sandbox Code Playgroud)

其中meta::is_pointer<T>对应当前std::is_pointer<T>类型.

c++ templates type-traits template-meta-programming c++11

23
推荐指数
1
解决办法
3433
查看次数