2017-08-27 40 views
1

下面的代碼如何僅在沒有其他轉換可用的情況下啓用構造函數模板?

#include <iostream> 
#include <type_traits> 

template <typename T> 
struct bar { 
    bar(const bar<T>&) { 
     std::cout << "copy ctor\n"; 
    } 

    template <typename U, 
     typename = std::enable_if_t<!std::is_convertible_v<U, bar<T>>>> 
    bar(U&&) { 
     std::cout << "ctor template\n"; 
    } 
}; 

struct foo { 
    operator bar<int>() const { 
     return bar<int>(1); 
    } 
    operator int() const { 
     return 2; 
    } 
}; 

int main() { 
    foo my_foo; 

    std::cout << "constructor: "; 
    bar<int> my_bar(my_foo); 

    std::cout << "static_cast: "; 
    my_bar = static_cast<bar<int>>(my_foo); 
} 

produces

constructor: ctor template 
static_cast: ctor template 

作爲輸出。

但是我希望bar的構造函數模板,即template <typename U> bar::bar(U&&)僅在U尚未轉換爲bar<T>時才能啓用。在foo的情況下,這種轉換已經在foo::operator bar<int>() const中給出。假設我是bar的作者,並且對foo或可能的類似類沒有任何瞭解(或影響)。我怎樣才能說服編譯器在這種情況下使用轉換操作符而不需要完全刪除bar的ctor模板?

+1

如果構造函數的數量相對較少,請使用這些構造函數定義一個輔助類,然後使用庫存SFINAE方法來查看是否可以構建輔助類。 –

+0

@SamVarshavchik謝謝,這是一個非常好的主意。但在我的情況下,我可以控制和更改'bar',但對'foo'和類似的類沒有任何知識或影響力。我只是把這個假設加到我的問題上。 –

+1

在第二種情況下,使用'static_cast',''ctor模板「'由'bar (1)'打印。似乎按預期工作。 –

回答

1

哦,它似乎已經在做我想要的。我不得不增加更多的打印語句看看吧:

#include <iostream> 
#include <type_traits> 

template <typename T> 
struct bar { 
    bar(const bar<T>&) { 
     std::cout << "copy ctor\n"; 
    } 
    template <typename U = T, 
     typename = std::enable_if_t<!std::is_convertible_v<U, bar<T>>>> 
    bar(U&& val) { 
     std::cout << "ctor template: " << val << "\n"; 
    } 
}; 

struct foo { 
    operator bar<int>() const { 
     std::cout << "operator bar<int>() -> "; 
     return bar<int>(1); 
    } 
    operator int() const { 
     std::cout << "operator int() -> "; 
     return 2; 
    } 
}; 

int main() { 
    foo my_foo; 

    std::cout << "constructor: "; 
    bar<int> my_opt(my_foo); 

    std::cout << "static_cast: "; 
    my_opt = static_cast<bar<int>>(my_foo); 
} 

outputs

constructor: operator optional<int>() -> ctor template: 1 
static_cast: operator optional<int>() -> ctor template: 1 

拷貝構造函數不會出現在輸出中,因爲返回值優化。

編輯:正如Barry在評論中指出的,這只是偶然的工作,並且可以lead to serious problems

+0

這實際上並不工作 - 請參閱[this](https://stackoverflow.com/q/32997699/2069064) – Barry

相關問題