Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何避免在模板类中重新定义typedef?_C++_Typedef - Fatal编程技术网

C++ 如何避免在模板类中重新定义typedef?

C++ 如何避免在模板类中重新定义typedef?,c++,typedef,C++,Typedef,我试图创建一个获取和设置的类,这取决于它是传递getter和setter,还是仅仅是一个指向要获取和设置的变量的指针。其思想是,当使用指针参数构造它时,TGetter和TSetter成员只是默认为chars,不做任何事情。如果使用setter和getter构造函数调用它,那么指向变量的指针默认为char,不做任何事情。我尝试使用std::enable_if和typedefs来确定T是什么,但我得到了多个定义: template <typename TGetter = char, typen

我试图创建一个获取和设置的类,这取决于它是传递getter和setter,还是仅仅是一个指向要获取和设置的变量的指针。其思想是,当使用指针参数构造它时,TGetter和TSetter成员只是默认为chars,不做任何事情。如果使用setter和getter构造函数调用它,那么指向变量的指针默认为char,不做任何事情。我尝试使用std::enable_if和typedefs来确定T是什么,但我得到了多个定义:

template <typename TGetter = char, typename TSetter = char, typename Tptr = char> 
struct GetterSetter  
    // IF THE PTR CONSTRUCTOR IS CALLED THEN I WANT T TO BE THE TYPE OF TGetter() called result.
    // IF THE GETTER AND SETTER CONSTRUCTOR IS CALLED I WANT T TO BE THE TYPE OF
    // T DEREFERENCED
{
    typedef std::enable_if<std::is_same_v<Tptr, char>, std::invoke_result_t<TGetter>> T;
    typedef std::enable_if < std::is_same_v<TGetter, char>, std::remove_pointer_t<Tptr>> T;
    

    GetterSetter(TGetter getter, TSetter setter) : getter(getter), setter(setter) {}
    GetterSetter(Tptr ptr) : ptrToT(ptr) {}

    TGetter getter;
    TSetter setter;
    Tptr ptrToT;

    T get()
    {
        if constexpr (std::is_same_v<Tptr, char>) return *ptrToT;
        else return getter();
    }

    void set(T t)
    {
        if constexpr (std::is_same_v<Tptr, char>) *ptrToT = t;
        else setter(t);
    }
};
模板
结构GetterSetter
//如果调用了PTR构造函数,那么我希望T是名为result的TGetter()的类型。
//如果调用GETTER和SETTER构造函数,我希望T是
//不去引用
{
typedef std::启用_if T;
typedef std::enable_ift;
GetterSetter(TGetter-getter,TSetter-setter):getter(getter),setter(setter){}
GetterSetter(Tptr-ptr):ptrToT(ptr){
更好的吸气剂;
切特设定器;
Tptr-ptrToT;
不明白
{
如果constexpr(std::is_same_v)返回*ptrToT;
else返回getter();
}
空集(T)
{
如果constexpr(std::is_same_v)*ptrToT=t;
else设定器(t);
}
};

如何预防?我根本没有实例化该类,并且我得到了重新定义编译器错误。

如果
有条件地选择
typedef
,则不能使用
std::enable\u。为此,您可以编写:

typedef std::conditional_t<std::is_same_v<TGetter, char>,
                           std::remove_pointer_t<Tptr>, 
                           std::invoke_result_t<TGetter>> T;
typedef std::conditional\u t;
或者最好:

using T = std::conditional_t<std::is_same_v<TGetter, char>,
                             std::remove_pointer_t<Tptr>, 
                             std::invoke_result_t<TGetter>>;
使用T=std::conditional\u T;

假设
T
必须是这两种类型中的一种。

std::enable_if
-base使用SFINAE和函数重载解析。typedef没有重载解析这回事。仅适用于函数和类。不能根据构造该类对象的方式选择类成员。T是这个班的一员。它独立于任何对象而存在。在我写这篇文章的方式中,代码总是使用getter和setter,但它有构造函数,这些构造函数接受适当类型的指针,并创建适当的lambda用作它的getter和setter。这似乎比尝试使用variable
typedef
s更干净一些。@Nathan Pierson是的,我认为这在课堂上可能更干净,但无论何时调用它,GetterSetter(&myvariable)之间的区别是什么;和GetterSetter([]{return myvariable;},[](int i){myvariable=i;});您可以在
T
上对类进行参数化,然后代替
TGetter getter你会喜欢
std::function getter。编写一个接受
T*
并生成相应lambda的ctor,然后编写一个直接接受getter和setter函数的ctor重载。调用代码仍然看起来像是
getterSetter.get()
getterSetter.set(newValue)
。哦,我明白了。如果案例是三个或更多,您是否需要将它们嵌套?读起来真让人困惑。嗯,可能吧。这可能取决于实际情况。编辑您的问题以要求三向选择,我将尝试更新答案。@Zebrafish带有专门化的模板别名可能是您需要三个或更多选项时的另一个选项。需要处理
TGetter
char
更好(当前尝试评估
std::invoke\u result\t
)。在这种情况下,
typename std::conditional\u t::type
可以工作。@cigien哦,对了。我们在考虑模板变量。