在/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) 假设我有:
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。
有没有办法在编译时实现这一点?
我有一个模板类,其中每个模板参数代表内部计算可以处理的一种类型的值.需要模板(而不是函数重载),因为值作为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成员中对我来说也不清楚.
谢谢你的帮助!
在这个答案中,我根据类型的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) 我正在尝试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) 我想知道是否有可能在编译时检查两种类型是否相同.我想出的是(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)这个功能黑客的地址保证按标准工作(我打赌不会:))?
在编写一个供个人使用的小模板元编程库时,我遇到了一个有趣的问题.
由于我正在为一些元函数重用一些部分特化,我决定将它们放在一个公共模板类下,并使用标签和嵌套的部分特化来提供行为上的差异.
问题是我得到了荒谬(对我而言)的结果.这是一个最小的例子,展示了我想要做的事情:
#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
使用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
基本上,我想要实现的是编译时验证(可能很好的错误消息)注册可调用(函数,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
类似的问题:为什么
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>类型.