在某些模板参数的模板函数上设置public / private

时间:2016-08-27 09:51:43

标签: c++ templates

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

class B{
    enum ENU{
        T0,T1,T2   
    }
    template<ENU T=T0> someType f(){  ... } //want T1,T2 = public,  T0 = private
};

当前用法(解决方案不应更改): -

B b;
int aa=b.f<T0>(); //should fail
std::string bb=b.f<T1>();// should ok

编辑: B有很多这样的功能。

以下是完整代码(以防万一有人想要编辑或使用)https://ideone.com/ryNCml

3 个答案:

答案 0 :(得分:2)

我怀疑你想要做什么是可能的,因为在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
}

如果您使用相同的函数实现,您可以将其转发到常用方法,或者只是将T0设为私有。

或者,您可以使用可以转换值的代理对象,但我不确定这是否是我熟悉的编译器扩展的标准C ++:

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> {};
}

答案 1 :(得分:2)

据我所知,您希望在调用成员方法var dFormat = "dd/MM/yyyy h:mm:ss tt"; 时禁止使用T0作为模板参数。 为此,您可以使用fstd::enable_if 它遵循一个最小的工作示例:

static_assert

答案 2 :(得分:0)

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

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>(); }

};

与您的要求相反,使用情况发生了变化 - 但这通常是最简单的方法:

B b;
int aa=b.fT0(); // fails
int bb=b.fT1();// ok

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

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

注意:后一种解决方案尚未提供给编译器。会有错别字。