2013-03-15 2 views
0

프로그램에서 가변 템플릿을 사용하고 있는데 예기치 않은 오류가 발생했습니다. 나는 오류를 격리하고 나는 그것을 충격을했습니다 당신이 선 "#INCLUDE iostream"를 삭제하면가변 템플릿이있는 희귀 버그?

#include<cctype> 
#include<iostream> // try to delete this line 

class A 
{ 
    public: 
     void constructor() 
     { } 

     template<typename... Args> 
     void constructor(int (*f)(int), Args... args) 
     { 
      // process(f) 
      constructor(args...); 
     } 

     template<typename... Args> 
     A(Args... args) 
     { 
      constructor(args...); 
     } 
}; 

int main() 
{ 
    A a; 
    a.constructor(std::isspace); // ok 

    A b(std::isspace); // error 

    return 0; 
} 

가, 소스가 확실히 컴파일됩니다.

prov.cpp: In function ‘int main()’: 
prov.cpp:32:22: error: no matching function for call to ‘A::A(<unresolved overloaded function type>)’ 
prov.cpp:32:22: note: candidates are: 
prov.cpp:18:7: note: A::A(Args ...) [with Args = {}] 
prov.cpp:18:7: note: candidate expects 0 arguments, 1 provided 
prov.cpp:4:7: note: constexpr A::A(const A&) 
prov.cpp:4:7: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘const A&’ 
prov.cpp:4:7: note: constexpr A::A(A&&) 
prov.cpp:4:7: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘A&&’ 

나는이 g ++ 버전을 사용하고 있습니다 :이 라인을 넣어 경우, 컴파일러에서 오류 던져 g를 ++ (4.7.2-11precise2/리나 우분투) 4.7.2 나는 컴파일하고있어 이 플래그 : g++ -Wall -pedantic -std=c++11 prov.cpp -o prov

왜 컴파일러가이 오류를 throw하는지 이해가 가지 않습니다. 가능한 버그입니까?

+2

오버로드 된 함수를 제공합니다. 컴파일러는 원하는 std :: isspace 중에서 과부하를 선택해야합니까? – PlasmaHH

+5

왜 즉시 컴파일러 버그라고 가정합니까? 그것은 대단히 확신합니다 ... –

+0

나는 그것이 컴파일러 버그라고 가정하지 않습니다. 제목에서 나는 의문문을 사용했고 포스트 i에서는 가능한 버그인지 궁금합니다. – xgbuils

답변

2

문제는 <cctype>는 하나의 함수 isspace을 정의하는,하지만 <iostream>를 추가하면 isspace 또 다른 과부하를 추가하는 <locale>에서 가져 왔습니다. <cctype>에서 하나는, <locale>에서 하나 포함 모두

template< class charT > 
bool isspace(charT ch, const locale& loc); 

입니다

int isspace(int ch); 

std::isspace이 모호하게하고, 따라서 코드가 실패합니다. 이것은 컴파일러가 전달할 내용을 결정할 수 없기 때문에 (constructor 대신) 실제 ctor를 통해 라우트 할 때만 표시됩니다. OTOH의 경우 constructor 메서드는 이미 두 오버로드에서 선택하는 방법을 컴파일러에 알려주는 매개 변수를 사용합니다.

+0

고맙습니다. 이제 문제를 해결했습니다. – xgbuils

3

이것은 컴파일러 버그가 아니거나 가변적 인 템플릿의 문제가 아니기 때문에 std::isspace은 단순히 오버로드됩니다. .constructor을 직접 호출하면 첫 번째 인수 int (*f)(int)은 올바른 오버로드를 선택하는 데 충분한 정보를 제공하지만 일반 인수는 그렇지 않습니다. 이것은 쉽게 예와 함께 설명된다 :

// our std::isspace 
void foo(int){} 
void foo(double){} 

void test1(void (*f)(int)){} 

template<class T> 
void test2(T v){} 

int main(){ 
    test1(foo); // compiles, compiler sees you want the 'int' overload 
    test2(foo); // error, compiler has no clue which overload you want 
       // and which type to deduce 'T' as 
} 

두 가지 방법으로이 문제를 해결할 수 있습니다

int (*f)(int) = std::isspace; // assign to variable, giving the compiler the information 
A b(f); // already has concrete type here 

// or 
A b(static_cast<int(*)(int)>(std::isspace)); // basically the same as above, in one step