C++ 为某个模板参数设置模板上的public/private函数

C++ 为某个模板参数设置模板上的public/private函数,c++,templates,C++,Templates,是否可以使某个模板函数对某个模板参数具有2个可访问性级别?(通过拆分为2个功能?) B类{ 枚举菜单{ T0,T1,T2 } 模板someType f(){…}//want T1,T2=public,T0=private }; 当前使用情况(解决方案不应更改):- B; int aa=b.f()//应该失败 std::string bb=b.f();//应该可以 编辑:B有很多类似的功能 这是完整的代码(以防有人想要编辑或使用)。如果您只想支持有限的模板参数集,我将编写三个不是模板函数的

是否可以使某个模板函数对某个模板参数具有2个可访问性级别?(通过拆分为2个功能?)

B类{
枚举菜单{
T0,T1,T2
}
模板someType f(){…}//want T1,T2=public,T0=private
};
当前使用情况(解决方案不应更改):-

B;
int aa=b.f()//应该失败
std::string bb=b.f();//应该可以
编辑:B有很多类似的功能




这是完整的代码(以防有人想要编辑或使用)。

如果您只想支持有限的模板参数集,我将编写三个不是模板函数的函数,并为它们提供正确的可见性。然后让他们委托一个私有模板函数来完成这项工作。这看起来像:

class B{
public:
    enum ENU{
        T0,T1,T2   
    }
private:
    template<ENU T=T0> int f(){ 
          std::cout<<"In enum "<<T<<std::endl;
          return 0;
    }

protected:
    someType fT0() { return f<T0>(); }
public:
    someType fT1() { return f<T1>(); }
    someType fT2() { return f<T2>(); }

};
或者,您可以将模板设置为公共模板,但为其提供一个伪参数(使用默认值),并使伪参数的类型取决于模板参数(通过traits)。如果虚拟对象的类型是私有类,则模板只能由成员调用

template <ENU T>
struct protection_traits;

class B{
friend class protection_traits<T0>; // So it has access to Protected.
protected:
    struct Protected{};
public:
    struct Public{};

    enum ENU{
        T0,T1,T2   
    }
    template<ENU T=T0> int f( typename protection_traits<T>::type = {})
      { std::cout<<"In enum "<<T<<std::endl; }
};

template <ENU T>
struct protection_traits 
{
    typedef B::Public type;   // Default to public
};
template<>
struct protection_traits<T0> 
{ 
    typedef B::Protected type;  // But T0 uses Protected
};
模板
结构保护特性;
B类{
friend class protection_traits;//因此它可以访问受保护的。
受保护的:
结构保护{};
公众:
结构公共{};
枚举菜单{
T0,T1,T2
}
模板intf(类型名保护特征::类型={})

{STD::Couth

我怀疑你想做的是可能的,因为C++中不允许有一个值上的专门函数。

如果不需要枚举,可以编写类似的代码:

class B {
public:
     struct T0{};
     struct T1{};
     struct T2{};
     template<typename T> void f(T, ...) {
          static_assert(std::is_same_v<T, T1> || std::is_same_v<T, T2>); 
     }
private:
     void f(T0, ...) {}
};

int main(int argc, char **argv) {
    B b{};
    b.f(T1{}); // Should compile
    b.f(T0{}); // Should not compile
}

据我所知,您希望禁止在调用成员方法
f
时使用
T0
作为模板参数
为此,您可以使用
std::enable_if
static_assert

下面是一个简单的工作示例:

#include<type_traits>

class B {
public:
    enum ENU { T0,T1,T2 };

    template<ENU T>
    std::enable_if_t<(T==T1||T==T2),int>
    f() { return 42; }

    template<ENU T>
    int g(){
        static_assert(T==T1||T==T2, "not allowed");
        return 42;
    }
};

int main() {
    B b;
    b.f<B::T1>();
    // It doesn't work
    //b.f<B::T0>();
    b.g<B::T1>();
    // It doesn't work
    //b.g<B::T0>();
}
#包括
B类{
公众:
枚举ENU{T0,T1,T2};
模板
std::如果启用,则启用
f(){return 42;}
模板
int g(){
静态断言(T==T1 | | T==T2,“不允许”);
返回42;
}
};
int main(){
B B;
b、 f();
//它不起作用
//b、 f();
b、 g();
//它不起作用
//b、 g();
}

Cool!我仍在努力管理成员模板函数专用化。我测试,它可以工作…但不像模板那样可爱,…谢谢!(投票表决)我在“使伪参数的类型取决于模板参数(通过特征)”方面迷失了方向,你能编辑我的完整代码吗(我编辑了问题)或者提供一些示例?他的意思是他希望您将使类唯一的某个特性作为参数传递。例如,如果您有一个car类,并且希望使其唯一,请将其创建一个接口“IIndentifier”,并将其用作模板模式(伪参数将获得一个IIdentifier作为其对象)是的……我可以解释,但只能含糊其辞(这有助于模板推断)不知道如何转换成代码……我只是C++的初学者……是什么?图式?那些是什么?都让我困惑……你能查一下完整的代码吗?我想我已经使用过那个技术了。那个接口是一个特性——它本身是一个模板,可以传递给原来的模板。你可以在网上搜索它的模板模板。它的
template <ENU T>
struct protection_traits;

class B{
friend class protection_traits<T0>; // So it has access to Protected.
protected:
    struct Protected{};
public:
    struct Public{};

    enum ENU{
        T0,T1,T2   
    }
    template<ENU T=T0> int f( typename protection_traits<T>::type = {})
      { std::cout<<"In enum "<<T<<std::endl; }
};

template <ENU T>
struct protection_traits 
{
    typedef B::Public type;   // Default to public
};
template<>
struct protection_traits<T0> 
{ 
    typedef B::Protected type;  // But T0 uses Protected
};
B b;
int aa=b.f<T0>(); // fails (no access to B::Protected)
int bb=b.f<T1>(); // ok
class B {
public:
     struct T0{};
     struct T1{};
     struct T2{};
     template<typename T> void f(T, ...) {
          static_assert(std::is_same_v<T, T1> || std::is_same_v<T, T2>); 
     }
private:
     void f(T0, ...) {}
};

int main(int argc, char **argv) {
    B b{};
    b.f(T1{}); // Should compile
    b.f(T0{}); // Should not compile
}
class B {
public:
    enum class T { //< Strong typed!
        T0,
        T1,
        T2
    }
    template <T t>
    struct TWrapper {};

    template <T ActualT>
    void f(..., TWrapper<ActualT> tw = TWrapper<ActualT>{}); 
private:
    template <>
    struct TWrapper<T0> {};
}
#include<type_traits>

class B {
public:
    enum ENU { T0,T1,T2 };

    template<ENU T>
    std::enable_if_t<(T==T1||T==T2),int>
    f() { return 42; }

    template<ENU T>
    int g(){
        static_assert(T==T1||T==T2, "not allowed");
        return 42;
    }
};

int main() {
    B b;
    b.f<B::T1>();
    // It doesn't work
    //b.f<B::T0>();
    b.g<B::T1>();
    // It doesn't work
    //b.g<B::T0>();
}