正如标题所述,我正在寻找枚举元组类型的最佳方法。 所以我的第一次尝试是下面的代码,它是对stackoverflow的另一个答案的改编,唯一的变化是包装在另一个类上,因此不需要将元组类型作为模板参数传递:
#include <tuple>
using namespace std;
using uInt = size_t;
template<typename... ARGS>
class ECS_Data
{
private:
tuple<ARGS...> data;
private:
//TYPE INDEXING
template<typename T, typename Types>
struct Internal_Type_Index;
template<typename T>
struct Type_Index {
static constexpr uInt value = Internal_Type_Index<T, tuple<ARGS...>>::value;
};
template<typename T, typename U, typename... Types>
struct Internal_Type_Index<T, tuple<U, Types...>> {
static constexpr uInt value = 1 + Internal_Type_Index<T, tuple<Types...>>::value;
};
template<typename T, typename... Types>
struct Internal_Type_Index<T, tuple<T, Types...>> {
static constexpr uInt value = 0;
};
public:
template<typename T>
static constexpr uInt Type_Index_v = Type_Index<T>::value;
};
int main()
{
ECS_Data<int,float,double,long long,char> ecs_data;
return ecs_data.Type_Index_v<char>; //return 4
}
“问题”是,对于具有50个类型的元组来说,它实例化了1350个结构,每个结构都带有一个静态变量。
例如,对于tuple<int,float,double>
:
用int
调用将实例化1个结构Internal_Type_Index<int, tuple<int, Types...>>
并停止,因为立即发现了int
。
用float
调用将实例化2个结构Internal_Type_Index<float, tuple<int, Types...>>
,然后Internal_Type_Index<float, tuple<float, Types...>>
然后停止,因为找到了float,以此类推...导致3 + 2 + 1实例化(假设为{{1 }}被所有类型调用。
那么Type_Index_v
实例化对吧? N + (N+N^2)/2
N
和Type_Index
(N+N^2)/2
部分专业化(全部1350中都有一个静态变量)。
我的第二个解决方法是:
Internal_Type_Index
还是以50个类型的元组为例,这次我们有:
#include <tuple>
#include <utility>
using namespace std;
using uInt = size_t;
template<typename... ARGS>
class ECS_Data
{
private:
tuple<ARGS...> data;
template<typename T>
inline static uInt _index = 0;
public:
ECS_Data() {
init_index(std::make_index_sequence<sizeof...(ARGS)>());
}
template<typename T>
uInt index()const { return _index<T>; }
private:
template<size_t... N>
void init_index(std::index_sequence<N...>) { (..., (_index<ARGS> = N)); }
};
int main()
{
ECS_Data<int,float,double,char> ecs_data;
return ecs_data.index<char>();
}
的2 + N个实例
来自make_index_sequence
的50个静态模板变量
_index
的50个成员函数实例化
从数字上看,这似乎更好,但是现在是运行时,因为像上面的代码中那样,用折叠表达式初始化index<T>()
constexpr时,我看不到一种方法。
所以我的问题是: 1)您是否看到一种改进上面代码的方法? 2)考虑到所有因素(例如编译器优化魔术),最终哪个版本更好? 3)您可以建议一个更好的版本? 编辑:原谅如果很难阅读,那么stackoverflow上的文本编辑器完全忽略了我的换行符。
答案 0 :(得分:2)
我会做的:
template <typename T, typename Tuple, std::size_t ... Is>
constexpr std::size_t tuple_index_impl(std::index_sequence<Is...>)
{
// You might adapt here to handle duplicate differently
return std::max({ std::is_same<T, std::tuple_element_t<Is, Tuple>>::value * (Is + 1)... });
}
template <typename T, typename Tuple>
constexpr std::size_t tuple_index()
{
return tuple_index_impl<T, Tuple>(std::make_index_sequence<std::tuple_size<Tuple>::value>());
}
通过类型+ std::index_sequence
对这两个方法进行一次实例化(这可能由编译器以1种唯一的实例化方式神奇地完成)。
答案 1 :(得分:1)
我只会在3点开枪。我的镜头看起来像这样:
import numpy as np
from scipy.optimize import curve_fit
concentration = np.array(
[
[0.6, 0.59642147, 0.5859375, 0.56603774, 0.53003534, 0.41899441],
[0.06, 0.11928429, 0.29296875, 0.62264151, 1.21908127, 3.05865922],
]
)
protein = concentration[0, :]
ligand = concentration[1, :]
titration_data = np.array(
[
[0, 0, 0.29888413, 0.45540198, 0.72436899, 1],
[0, 0, 0.11930228, 0.35815982, 0.59396978, 1],
[0, 0, 0.30214337, 0.46685577, 0.79007708, 1],
[0, 0, 0.27204954, 0.56702549, 0.84013344, 1],
[0, 0, 0.266836, 0.43993175, 0.74044123, 1],
[0, 0, 0.28179148, 0.42406587, 0.77048624, 1],
[0, 0, 0.2281092, 0.50336244, 0.79089151, 0.87029517],
[0, 0, 0.18317694, 0.55478412, 0.78448465, 1],
]
)
def fun(_, kd):
a = protein
b = protein + ligand
c = ligand
return np.array((b + kd - np.sqrt(((b + kd) ** 2) - 4 * a * c)) / (2 * a))
def glob_fun(_, kd):
return np.tile(fun(_, kd), len(titration_data))
x = ligand
y = titration_data
popt, pcov = curve_fit(glob_fun, x, y.ravel())
可以像
那样使用let chai = require("chai").use(require("chai-as-promised"));
import { defineSupportCode } from 'cucumber';
import {browser, element, by, ElementFinder, $, $$ , until } from 'protractor' ;
const expect = chai.expect;
import { HomePage } from '../page-objects/pm360-home-page';
import { LoginPage } from '../page-objects/pm360-login-page';
var pm360_homepage = new HomePage();
//var pm360_loginpage = new LoginPage();
defineSupportCode(({Given,Then }) => {
Given('I login into pm360 page with a valid authentication {string} and {string}',
async function givenauth(username: string, password: string): Promise<void>{
pm360_homepage.OpenBrowser('https://pm360-qa.parkmobile.io/');
await pm360_homepage.usernameField.sendKeys('.....');
await pm360_homepage.passwordField.sendKeys('......');
//browser.actions().sendKeys(protractor.Button.MIDDLE).click();
pm360_homepage.ClickLogIn();
//pm360_homepage.logInBtn.click().then(()=> {"looged In"});
//browser.touchActions().tap(pm360_homepage.logInBtn).perform().then(()=> {"logged In"});
browser.ignoreSynchronization = true;
});
Given('I navigate through manage policies',
async function givenmanaging():Promise<void>{
browser.ignoreSynchronization = true;
//browser.wait(until.elementsLocated(pm360_homepage.managePoliciesBtn));
await pm360_homepage.managePoliciesBtn.click();
//browser.waitForAngularEnabled(true);
实时:http://coliru.stacked-crooked.com/a/8ea39202298f2ddc
这里的键是template <typename Tuple, typename Needle, std::size_t... I>
constexpr std::size_t tuple_index_impl(std::index_sequence<I...>) {
// don't use std::disjunction_v here as it will return bool
constexpr std::size_t idx = std::disjunction<
// need I+1 to prevent a falsy result on index 0
std::integral_constant<std::size_t,
(I+1) * std::is_same_v<std::tuple_element_t<I, Tuple>, Needle>>...,
// fallthrough case
std::integral_constant<std::size_t, 0>
>::value;
static_assert(idx != 0, "type not found in tuple");
return idx - 1;
}
template <typename Tuple, typename Needle>
constexpr std::size_t tuple_index() {
return tuple_index_impl<Tuple, Needle>(
std::make_index_sequence<std::tuple_size_v<Tuple>>{});
}
,在找到值之后,不需要实例化任何模板参数。这也适用于任何类似元组的类型(实现using T = std::tuple<int, long long, double, char, double>;
//std::cout << tuple_index<T, float>(); //ERROR: type not found in tuple
std::cout << tuple_index<T, double>(); // prints "2", the first one
std::cout << tuple_index<T, char>(); // prints "3"
和std::disjunction
接口的事物)。
由于这显然是tuple_element
/模板的全部魔力,因此唯一需要付出的代价就是在编译时。我猜想这在这方面的性能如何取决于编译器tuple_size
实现的效率,但是我没有做任何分析。